From 4f5c655fcd6fa1bc32fb3050bb2b4c58deb41741 Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Tue, 10 Sep 2024 08:51:30 -0400 Subject: [PATCH 01/41] Add unit tests --- testutil/random/hex.go | 19 ++ .../aggregated_key_share_request_test.go | 59 ++++++ .../keeper/aggregated_key_share_test.go | 64 +++++++ x/keyshare/keeper/authorized_address_test.go | 66 +++++++ x/keyshare/keeper/commitments_test.go | 75 ++++++++ x/keyshare/keeper/general_key_share_test.go | 70 +++++++ x/keyshare/keeper/key_share_test.go | 65 +++++++ .../keeper/last_submitted_height_test.go | 30 +++ x/keyshare/keeper/pub_key_test.go | 70 +++++++ .../keeper/query_aggregated_key_share_test.go | 171 ++++++++++++++++++ .../keeper/query_authorized_address_test.go | 171 ++++++++++++++++++ x/keyshare/keeper/validator_set_test.go | 63 +++++++ 12 files changed, 923 insertions(+) create mode 100644 testutil/random/hex.go create mode 100644 x/keyshare/keeper/aggregated_key_share_request_test.go create mode 100644 x/keyshare/keeper/aggregated_key_share_test.go create mode 100644 x/keyshare/keeper/authorized_address_test.go create mode 100644 x/keyshare/keeper/commitments_test.go create mode 100644 x/keyshare/keeper/general_key_share_test.go create mode 100644 x/keyshare/keeper/key_share_test.go create mode 100644 x/keyshare/keeper/last_submitted_height_test.go create mode 100644 x/keyshare/keeper/pub_key_test.go create mode 100644 x/keyshare/keeper/query_aggregated_key_share_test.go create mode 100644 x/keyshare/keeper/query_authorized_address_test.go create mode 100644 x/keyshare/keeper/validator_set_test.go diff --git a/testutil/random/hex.go b/testutil/random/hex.go new file mode 100644 index 00000000..55210c3e --- /dev/null +++ b/testutil/random/hex.go @@ -0,0 +1,19 @@ +package random + +import ( + "encoding/hex" + "math/rand" + "time" +) + +// RandHex returns a random hexadecimal string of length n. +func RandHex(n int) string { + src := rand.New(rand.NewSource(time.Now().UnixNano())) + b := make([]byte, (n+1)/2) + + if _, err := src.Read(b); err != nil { + panic(err) + } + + return hex.EncodeToString(b)[:n] +} diff --git a/x/keyshare/keeper/aggregated_key_share_request_test.go b/x/keyshare/keeper/aggregated_key_share_request_test.go new file mode 100644 index 00000000..7ecceeb8 --- /dev/null +++ b/x/keyshare/keeper/aggregated_key_share_request_test.go @@ -0,0 +1,59 @@ +package keeper_test + +import ( + "fmt" + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "testing" +) + +func createNKeyshareRequest(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.KeyShareRequest { + items := make([]types.KeyShareRequest, n) + for i := range items { + items[i].RequestId = fmt.Sprintf("%d/rq", i) + items[i].Identity = fmt.Sprintf("%d/rq", i) + keeper.SetKeyShareRequest(ctx, items[i]) + } + return items +} + +func TestKeyShareRequestGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNKeyshareRequest(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetKeyShareRequest(ctx, + item.Identity, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} +func TestKeyShareRequestRemove(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNKeyshareRequest(&keeper, ctx, 10) + for _, item := range items { + keeper.RemoveKeyShareRequest(ctx, + item.Identity, + ) + _, found := keeper.GetKeyShareRequest(ctx, + item.Identity, + ) + require.False(t, found) + } +} + +func TestKeyShareRequestGetAll(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNKeyshareRequest(&keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllKeyShareRequests(ctx)), + ) +} diff --git a/x/keyshare/keeper/aggregated_key_share_test.go b/x/keyshare/keeper/aggregated_key_share_test.go new file mode 100644 index 00000000..6c8110e3 --- /dev/null +++ b/x/keyshare/keeper/aggregated_key_share_test.go @@ -0,0 +1,64 @@ +package keeper_test + +import ( + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func createNAggregatedKeyShare(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.AggregatedKeyShare { + items := make([]types.AggregatedKeyShare, n) + for i := range items { + items[i].Height = uint64(i) + + keeper.SetAggregatedKeyShare(ctx, items[i]) + } + return items +} + +func TestAggregatedKeyShareGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNAggregatedKeyShare(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetAggregatedKeyShare(ctx, + item.Height, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} +func TestAggregatedKeyShareRemove(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNAggregatedKeyShare(&keeper, ctx, 10) + for _, item := range items { + keeper.RemoveAggregatedKeyShare(ctx, + item.Height, + ) + _, found := keeper.GetAggregatedKeyShare(ctx, + item.Height, + ) + require.False(t, found) + } +} + +func TestAggregatedKeyShareGetAll(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNAggregatedKeyShare(&keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllAggregatedKeyShare(ctx)), + ) +} diff --git a/x/keyshare/keeper/authorized_address_test.go b/x/keyshare/keeper/authorized_address_test.go new file mode 100644 index 00000000..f1a79063 --- /dev/null +++ b/x/keyshare/keeper/authorized_address_test.go @@ -0,0 +1,66 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/sample" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func createNAuthorizedAddress(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.AuthorizedAddress { + items := make([]types.AuthorizedAddress, n) + for i := range items { + items[i].IsAuthorized = true + items[i].AuthorizedBy = sample.AccAddress() + items[i].Target = sample.AccAddress() + + keeper.SetAuthorizedAddress(ctx, items[i]) + } + return items +} + +func TestAuthorizedAddressGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNAuthorizedAddress(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetAuthorizedAddress(ctx, + item.Target, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} +func TestAuthorizedAddressRemove(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNAuthorizedAddress(&keeper, ctx, 10) + for _, item := range items { + keeper.RemoveAuthorizedAddress(ctx, + item.Target, + ) + _, found := keeper.GetAuthorizedAddress(ctx, + item.Target, + ) + require.False(t, found) + } +} + +func TestAuthorizedAddressGetAll(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNAuthorizedAddress(&keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllAuthorizedAddress(ctx)), + ) +} diff --git a/x/keyshare/keeper/commitments_test.go b/x/keyshare/keeper/commitments_test.go new file mode 100644 index 00000000..bf618096 --- /dev/null +++ b/x/keyshare/keeper/commitments_test.go @@ -0,0 +1,75 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func createNCommitments(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Commitments { + items := make([]types.Commitments, n) + for i := range items { + commitments := make([]string, n) + for j := 0; j < n; j++ { + commitments[j] = random.RandHex(10) + } + items[i].Commitments = commitments + keeper.SetActiveCommitments(ctx, items[i]) + keeper.SetQueuedCommitments(ctx, items[i]) + } + return items +} + +func TestActiveCommitmentsGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNCommitments(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetActiveCommitments(ctx) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} + +func TestQueuedCommitmentsGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNCommitments(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetQueuedCommitments(ctx) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} + +func TestActiveCommitmentsRemove(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + createNCommitments(&keeper, ctx, 10) + _, found := keeper.GetActiveCommitments(ctx) + require.True(t, found) + + keeper.DeleteActiveCommitments(ctx) + _, found = keeper.GetActiveCommitments(ctx) + require.False(t, found) +} + +func TestQueuedCommitmentsRemove(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + createNCommitments(&keeper, ctx, 10) + _, found := keeper.GetQueuedCommitments(ctx) + require.True(t, found) + + keeper.DeleteQueuedCommitments(ctx) + _, found = keeper.GetQueuedCommitments(ctx) + require.False(t, found) +} diff --git a/x/keyshare/keeper/general_key_share_test.go b/x/keyshare/keeper/general_key_share_test.go new file mode 100644 index 00000000..fe5db5e1 --- /dev/null +++ b/x/keyshare/keeper/general_key_share_test.go @@ -0,0 +1,70 @@ +package keeper_test + +import ( + "fmt" + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func createNGeneralKeyShares(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.GeneralKeyShare { + items := make([]types.GeneralKeyShare, n) + for i := range items { + items[i].Validator = sample.AccAddress() + items[i].IdValue = fmt.Sprintf("testing/%d", i) + items[i].IdType = "testing" + items[i].KeyShare = random.RandHex(10) + keeper.SetGeneralKeyShare(ctx, items[i]) + } + return items +} + +func TestGeneralKeyShareGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNGeneralKeyShares(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetGeneralKeyShare(ctx, + item.Validator, + item.IdType, + item.IdValue, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} + +func TestGeneralKeySharesRemove(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNGeneralKeyShares(&keeper, ctx, 10) + + keeper.RemoveGeneralKeyShare(ctx, + items[0].Validator, + items[0].IdType, + items[0].IdValue, + ) + _, found := keeper.GetGeneralKeyShare(ctx, + items[0].Validator, + items[0].IdType, + items[0].IdValue, + ) + require.False(t, found) +} + +func TestGeneralKeySharesGetAll(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNGeneralKeyShares(&keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllGeneralKeyShare(ctx)), + ) +} diff --git a/x/keyshare/keeper/key_share_test.go b/x/keyshare/keeper/key_share_test.go new file mode 100644 index 00000000..4951b5f1 --- /dev/null +++ b/x/keyshare/keeper/key_share_test.go @@ -0,0 +1,65 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func createNKeyShares(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.KeyShare { + items := make([]types.KeyShare, n) + for i := range items { + items[i].Validator = sample.AccAddress() + items[i].KeyShare = random.RandHex(10) + items[i].BlockHeight = uint64(i) + keeper.SetKeyShare(ctx, items[i]) + } + return items +} + +func TestKeyShareGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNKeyShares(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetKeyShare(ctx, + item.Validator, + item.BlockHeight, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} + +func TestKeySharesRemove(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNKeyShares(&keeper, ctx, 10) + + keeper.RemoveKeyShare(ctx, + items[0].Validator, + items[0].BlockHeight, + ) + _, found := keeper.GetKeyShare(ctx, + items[0].Validator, + items[0].BlockHeight, + ) + require.False(t, found) +} + +func TestKeySharesGetAll(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNKeyShares(&keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllKeyShare(ctx)), + ) +} diff --git a/x/keyshare/keeper/last_submitted_height_test.go b/x/keyshare/keeper/last_submitted_height_test.go new file mode 100644 index 00000000..bb9661af --- /dev/null +++ b/x/keyshare/keeper/last_submitted_height_test.go @@ -0,0 +1,30 @@ +package keeper_test + +import ( + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/testutil/sample" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "math/rand" + "strconv" + "testing" +) + +func createLastSubmittedHeight(keeper *keeper.Keeper, ctx sdk.Context) (string, string) { + randomValidator := sample.AccAddress() + randomHeight := strconv.FormatUint(rand.Uint64(), 10) + keeper.SetLastSubmittedHeight(ctx, randomValidator, randomHeight) + return randomValidator, randomHeight +} + +func TestLastSubmittedHeightGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + val, generatedHeight := createLastSubmittedHeight(&keeper, ctx) + height := strconv.FormatUint(keeper.GetLastSubmittedHeight(ctx, val), 10) + require.Equal(t, + nullify.Fill(generatedHeight), + nullify.Fill(height), + ) +} diff --git a/x/keyshare/keeper/pub_key_test.go b/x/keyshare/keeper/pub_key_test.go new file mode 100644 index 00000000..02024f7a --- /dev/null +++ b/x/keyshare/keeper/pub_key_test.go @@ -0,0 +1,70 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "math/rand" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func createActivePubKeys(keeper *keeper.Keeper, ctx sdk.Context) types.ActivePubKey { + var items types.ActivePubKey + items.PublicKey = random.RandHex(10) + items.Expiry = rand.Uint64() + items.NumberOfValidators = rand.Uint64() + keeper.SetActivePubKey(ctx, items) + return items +} + +func createQueuedPubKeys(keeper *keeper.Keeper, ctx sdk.Context) types.QueuedPubKey { + var items types.QueuedPubKey + items.PublicKey = random.RandHex(10) + items.Expiry = rand.Uint64() + items.NumberOfValidators = rand.Uint64() + keeper.SetQueuedPubKey(ctx, items) + return items +} + +func TestActivePubKeyGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + item := createActivePubKeys(&keeper, ctx) + rst, found := keeper.GetActivePubKey(ctx) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) +} + +func TestQueuedPubKeyGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + item := createQueuedPubKeys(&keeper, ctx) + rst, found := keeper.GetQueuedPubKey(ctx) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) +} + +func TestActivePubKeyRemoved(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + createActivePubKeys(&keeper, ctx) + keeper.DeleteActivePubKey(ctx) + _, found := keeper.GetActivePubKey(ctx) + require.False(t, found) +} + +func TestQueuedPubKeyRemoved(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + createQueuedPubKeys(&keeper, ctx) + keeper.DeleteQueuedPubKey(ctx) + _, found := keeper.GetQueuedPubKey(ctx) + require.False(t, found) +} diff --git a/x/keyshare/keeper/query_aggregated_key_share_test.go b/x/keyshare/keeper/query_aggregated_key_share_test.go new file mode 100644 index 00000000..bce00426 --- /dev/null +++ b/x/keyshare/keeper/query_aggregated_key_share_test.go @@ -0,0 +1,171 @@ +package keeper_test + +import ( + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestAggregatedKeyShareQuerySingle(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNAggregatedKeyShare(&keeper, ctx, 2) + for _, tc := range []struct { + desc string + request *types.QueryGetAggregatedKeyShareRequest + response *types.QueryGetAggregatedKeyShareResponse + err error + }{ + { + desc: "First", + request: &types.QueryGetAggregatedKeyShareRequest{ + Height: msgs[0].Height, + }, + response: &types.QueryGetAggregatedKeyShareResponse{AggregatedKeyShare: msgs[0]}, + }, + { + desc: "Second", + request: &types.QueryGetAggregatedKeyShareRequest{ + Height: msgs[1].Height, + }, + response: &types.QueryGetAggregatedKeyShareResponse{AggregatedKeyShare: msgs[1]}, + }, + { + desc: "KeyNotFound", + request: &types.QueryGetAggregatedKeyShareRequest{ + Height: msgs[1].Height * 2, + }, + err: status.Error(codes.NotFound, "not found"), + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.AggregatedKeyShare(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestAggregatedKeyShareQueryAllNoPagination(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNAggregatedKeyShare(&keeper, ctx, 10) + for _, tc := range []struct { + desc string + request *types.QueryAllAggregatedKeyShareRequest + response *types.QueryAllAggregatedKeyShareResponse + err error + }{ + { + desc: "QueryAll", + request: &types.QueryAllAggregatedKeyShareRequest{ + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 0, + CountTotal: false, + Reverse: false, + }, + }, + response: &types.QueryAllAggregatedKeyShareResponse{ + AggregatedKeyShare: msgs, + Pagination: &query.PageResponse{ + NextKey: nil, + Total: 10, + }, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.AggregatedKeyShareAll(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestAggregatedKeyShareQueryPaginated(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNAggregatedKeyShare(&keeper, ctx, 5) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllAggregatedKeyShareRequest { + return &types.QueryAllAggregatedKeyShareRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.AggregatedKeyShareAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.AggregatedKeyShare), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.AggregatedKeyShare), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.AggregatedKeyShareAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.AggregatedKeyShare), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.AggregatedKeyShare), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.AggregatedKeyShareAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.AggregatedKeyShare), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.AggregatedKeyShareAll(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) + }) +} diff --git a/x/keyshare/keeper/query_authorized_address_test.go b/x/keyshare/keeper/query_authorized_address_test.go new file mode 100644 index 00000000..07582f00 --- /dev/null +++ b/x/keyshare/keeper/query_authorized_address_test.go @@ -0,0 +1,171 @@ +package keeper_test + +import ( + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestAuthorizedAddressQuerySingle(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNAuthorizedAddress(&keeper, ctx, 2) + for _, tc := range []struct { + desc string + request *types.QueryGetAuthorizedAddressRequest + response *types.QueryGetAuthorizedAddressResponse + err error + }{ + { + desc: "First", + request: &types.QueryGetAuthorizedAddressRequest{ + Target: msgs[0].Target, + }, + response: &types.QueryGetAuthorizedAddressResponse{AuthorizedAddress: msgs[0]}, + }, + { + desc: "Second", + request: &types.QueryGetAuthorizedAddressRequest{ + Target: msgs[1].Target, + }, + response: &types.QueryGetAuthorizedAddressResponse{AuthorizedAddress: msgs[1]}, + }, + { + desc: "AuthorizedAddressNotFound", + request: &types.QueryGetAuthorizedAddressRequest{ + Target: strconv.Itoa(100000), + }, + err: types.ErrAuthorizedAddrNotFound, + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.AuthorizedAddress(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestAuthorizedAddressQueryAllNoPagination(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNAuthorizedAddress(&keeper, ctx, 12) + for _, tc := range []struct { + desc string + request *types.QueryAllAuthorizedAddressRequest + response *types.QueryAllAuthorizedAddressResponse + err error + }{ + { + desc: "QueryAllAuthorizedAddress", + request: &types.QueryAllAuthorizedAddressRequest{ + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 0, + CountTotal: false, + Reverse: false, + }, + }, + response: &types.QueryAllAuthorizedAddressResponse{ + AuthorizedAddress: msgs, + Pagination: &query.PageResponse{ + NextKey: nil, + Total: 12, + }, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.AuthorizedAddressAll(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestAuthorizedAddressQueryPaginated(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNAuthorizedAddress(&keeper, ctx, 5) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllAuthorizedAddressRequest { + return &types.QueryAllAuthorizedAddressRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.AuthorizedAddressAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.AuthorizedAddress), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.AuthorizedAddress), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.AuthorizedAddressAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.AuthorizedAddress), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.AuthorizedAddress), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.AuthorizedAddressAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.AuthorizedAddress), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.AuthorizedAddressAll(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) + }) +} diff --git a/x/keyshare/keeper/validator_set_test.go b/x/keyshare/keeper/validator_set_test.go new file mode 100644 index 00000000..d5854188 --- /dev/null +++ b/x/keyshare/keeper/validator_set_test.go @@ -0,0 +1,63 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func createNValidatorSet(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.ValidatorSet { + items := make([]types.ValidatorSet, n) + for i := range items { + addr := sample.AccAddress() + items[i].Validator = addr + items[i].Index = random.RandHex(10) + items[i].IsActive = true + keeper.SetValidatorSet(ctx, items[i]) + } + return items +} + +func TestValidatorSetGet(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNValidatorSet(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetValidatorSet(ctx, + item.Index, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} + +func TestValidatorSetRemove(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNValidatorSet(&keeper, ctx, 10) + + keeper.RemoveValidatorSet(ctx, + items[0].Index, + ) + _, found := keeper.GetValidatorSet(ctx, + items[0].Index, + ) + require.False(t, found) +} + +func TestValidatorSetGetAll(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + items := createNValidatorSet(&keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllValidatorSet(ctx)), + ) +} From 14f0f04917350b5c94e6baf4b8f5db03690523b1 Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Wed, 11 Sep 2024 10:13:24 -0400 Subject: [PATCH 02/41] Add query commits, keyshare & general keyshares unit test --- x/keyshare/keeper/query_commitments_test.go | 49 +++++ .../keeper/query_general_key_share_test.go | 177 ++++++++++++++++++ x/keyshare/keeper/query_key_share_test.go | 176 +++++++++++++++++ 3 files changed, 402 insertions(+) create mode 100644 x/keyshare/keeper/query_commitments_test.go create mode 100644 x/keyshare/keeper/query_general_key_share_test.go create mode 100644 x/keyshare/keeper/query_key_share_test.go diff --git a/x/keyshare/keeper/query_commitments_test.go b/x/keyshare/keeper/query_commitments_test.go new file mode 100644 index 00000000..3ad76fc6 --- /dev/null +++ b/x/keyshare/keeper/query_commitments_test.go @@ -0,0 +1,49 @@ +package keeper_test + +import ( + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestCommitmentsQuery(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNCommitments(&keeper, ctx, 1) + for _, tc := range []struct { + desc string + request *types.QueryCommitmentsRequest + response *types.QueryCommitmentsResponse + err error + }{ + { + desc: "QueryCommitments", + request: &types.QueryCommitmentsRequest{}, + response: &types.QueryCommitmentsResponse{ + ActiveCommitments: &msgs[0], + QueuedCommitments: &msgs[0], + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.Commitments(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} diff --git a/x/keyshare/keeper/query_general_key_share_test.go b/x/keyshare/keeper/query_general_key_share_test.go new file mode 100644 index 00000000..11d29e91 --- /dev/null +++ b/x/keyshare/keeper/query_general_key_share_test.go @@ -0,0 +1,177 @@ +package keeper_test + +import ( + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestGeneralKeyShareQuerySingle(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNGeneralKeyShares(&keeper, ctx, 2) + for _, tc := range []struct { + desc string + request *types.QueryGetGeneralKeyShareRequest + response *types.QueryGetGeneralKeyShareResponse + err error + }{ + { + desc: "First", + request: &types.QueryGetGeneralKeyShareRequest{ + Validator: msgs[0].Validator, + IdType: msgs[0].IdType, + IdValue: msgs[0].IdValue, + }, + response: &types.QueryGetGeneralKeyShareResponse{GeneralKeyShare: msgs[0]}, + }, + { + desc: "Second", + request: &types.QueryGetGeneralKeyShareRequest{ + Validator: msgs[1].Validator, + IdType: msgs[1].IdType, + IdValue: msgs[1].IdValue, + }, + response: &types.QueryGetGeneralKeyShareResponse{GeneralKeyShare: msgs[1]}, + }, + { + desc: "KeyNotFound", + request: &types.QueryGetGeneralKeyShareRequest{ + Validator: strconv.Itoa(100000), + IdType: strconv.Itoa(100000), + IdValue: strconv.Itoa(100000), + }, + err: status.Error(codes.NotFound, "not found"), + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.GeneralKeyShare(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestGeneralKeyShareQueryAllNoPagination(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNGeneralKeyShares(&keeper, ctx, 10) + for _, tc := range []struct { + desc string + request *types.QueryAllGeneralKeyShareRequest + response *types.QueryAllGeneralKeyShareResponse + err error + }{ + { + desc: "QueryAllGeneralKeyShare", + request: &types.QueryAllGeneralKeyShareRequest{ + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 0, + CountTotal: false, + Reverse: false, + }, + }, + response: &types.QueryAllGeneralKeyShareResponse{ + GeneralKeyShare: msgs, + Pagination: &query.PageResponse{ + NextKey: nil, + Total: 10, + }, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.GeneralKeyShareAll(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestGeneralKeyShareQueryPaginated(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNGeneralKeyShares(&keeper, ctx, 5) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllGeneralKeyShareRequest { + return &types.QueryAllGeneralKeyShareRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.GeneralKeyShareAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.GeneralKeyShare), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.GeneralKeyShare), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.GeneralKeyShareAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.GeneralKeyShare), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.GeneralKeyShare), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.GeneralKeyShareAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.GeneralKeyShare), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.GeneralKeyShareAll(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) + }) +} diff --git a/x/keyshare/keeper/query_key_share_test.go b/x/keyshare/keeper/query_key_share_test.go new file mode 100644 index 00000000..9262a2bc --- /dev/null +++ b/x/keyshare/keeper/query_key_share_test.go @@ -0,0 +1,176 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/sample" + "math/rand" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestKeyShareQuerySingle(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNKeyShares(&keeper, ctx, 2) + for _, tc := range []struct { + desc string + request *types.QueryGetKeyShareRequest + response *types.QueryGetKeyShareResponse + err error + }{ + { + desc: "First", + request: &types.QueryGetKeyShareRequest{ + Validator: msgs[0].Validator, + BlockHeight: msgs[0].BlockHeight, + }, + response: &types.QueryGetKeyShareResponse{KeyShare: msgs[0]}, + }, + { + desc: "Second", + request: &types.QueryGetKeyShareRequest{ + Validator: msgs[1].Validator, + BlockHeight: msgs[1].BlockHeight, + }, + response: &types.QueryGetKeyShareResponse{KeyShare: msgs[1]}, + }, + { + desc: "KeyNotFound", + request: &types.QueryGetKeyShareRequest{ + Validator: sample.AccAddress(), + BlockHeight: rand.Uint64(), + }, + err: status.Error(codes.NotFound, "not found"), + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.KeyShare(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestKeyShareQueryAllNoPagination(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNKeyShares(&keeper, ctx, 10) + for _, tc := range []struct { + desc string + request *types.QueryAllKeyShareRequest + response *types.QueryAllKeyShareResponse + err error + }{ + { + desc: "QueryAllKeyShare", + request: &types.QueryAllKeyShareRequest{ + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 0, + CountTotal: false, + Reverse: false, + }, + }, + response: &types.QueryAllKeyShareResponse{ + KeyShare: msgs, + Pagination: &query.PageResponse{ + NextKey: nil, + Total: 10, + }, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.KeyShareAll(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestKeyShareQueryPaginated(t *testing.T) { + keeper, ctx := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNKeyShares(&keeper, ctx, 5) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllKeyShareRequest { + return &types.QueryAllKeyShareRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.KeyShareAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.KeyShare), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.KeyShare), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.KeyShareAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.KeyShare), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.KeyShare), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.KeyShareAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.KeyShare), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.KeyShareAll(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) + }) +} From 9ef2b2a9fed78aacc267ee9537d513934bbf2b4f Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Wed, 25 Sep 2024 19:57:24 +0530 Subject: [PATCH 03/41] adding tx to register contract --- api/fairyring/pep/request_id.pulsar.go | 1827 +++++++++++++++++++++++- api/fairyring/pep/tx.pulsar.go | 1176 ++++++++++++++- api/fairyring/pep/tx_grpc.pb.go | 37 + app/ibc.go | 27 +- app/pep.go | 2 + go.mod | 2 + go.sum | 2 + proto/fairyring/pep/request_id.proto | 16 + proto/fairyring/pep/tx.proto | 9 + x/pep/keeper/contract.go | 100 ++ x/pep/keeper/keeper.go | 7 + x/pep/keeper/msg_register_contract.go | 42 + x/pep/module/module.go | 17 + x/pep/types/expected_keepers.go | 5 + x/pep/types/key_request_id.go | 1 + x/pep/types/request_id.pb.go | 773 +++++++++- x/pep/types/tx.pb.go | 540 ++++++- 17 files changed, 4401 insertions(+), 182 deletions(-) create mode 100644 x/pep/keeper/contract.go create mode 100644 x/pep/keeper/msg_register_contract.go diff --git a/api/fairyring/pep/request_id.pulsar.go b/api/fairyring/pep/request_id.pulsar.go index a0f16240..68c3b636 100644 --- a/api/fairyring/pep/request_id.pulsar.go +++ b/api/fairyring/pep/request_id.pulsar.go @@ -1184,6 +1184,1596 @@ func (x *fastReflection_PrivateRequest) ProtoMethods() *protoiface.Methods { } } +var ( + md_ContractDetails protoreflect.MessageDescriptor + fd_ContractDetails_registrar protoreflect.FieldDescriptor + fd_ContractDetails_contract_address protoreflect.FieldDescriptor +) + +func init() { + file_fairyring_pep_request_id_proto_init() + md_ContractDetails = File_fairyring_pep_request_id_proto.Messages().ByName("ContractDetails") + fd_ContractDetails_registrar = md_ContractDetails.Fields().ByName("registrar") + fd_ContractDetails_contract_address = md_ContractDetails.Fields().ByName("contract_address") +} + +var _ protoreflect.Message = (*fastReflection_ContractDetails)(nil) + +type fastReflection_ContractDetails ContractDetails + +func (x *ContractDetails) ProtoReflect() protoreflect.Message { + return (*fastReflection_ContractDetails)(x) +} + +func (x *ContractDetails) slowProtoReflect() protoreflect.Message { + mi := &file_fairyring_pep_request_id_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_ContractDetails_messageType fastReflection_ContractDetails_messageType +var _ protoreflect.MessageType = fastReflection_ContractDetails_messageType{} + +type fastReflection_ContractDetails_messageType struct{} + +func (x fastReflection_ContractDetails_messageType) Zero() protoreflect.Message { + return (*fastReflection_ContractDetails)(nil) +} +func (x fastReflection_ContractDetails_messageType) New() protoreflect.Message { + return new(fastReflection_ContractDetails) +} +func (x fastReflection_ContractDetails_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_ContractDetails +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_ContractDetails) Descriptor() protoreflect.MessageDescriptor { + return md_ContractDetails +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_ContractDetails) Type() protoreflect.MessageType { + return _fastReflection_ContractDetails_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_ContractDetails) New() protoreflect.Message { + return new(fastReflection_ContractDetails) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_ContractDetails) Interface() protoreflect.ProtoMessage { + return (*ContractDetails)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_ContractDetails) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Registrar != "" { + value := protoreflect.ValueOfString(x.Registrar) + if !f(fd_ContractDetails_registrar, value) { + return + } + } + if x.ContractAddress != "" { + value := protoreflect.ValueOfString(x.ContractAddress) + if !f(fd_ContractDetails_contract_address, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_ContractDetails) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "fairyring.pep.ContractDetails.registrar": + return x.Registrar != "" + case "fairyring.pep.ContractDetails.contract_address": + return x.ContractAddress != "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ContractDetails")) + } + panic(fmt.Errorf("message fairyring.pep.ContractDetails does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ContractDetails) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "fairyring.pep.ContractDetails.registrar": + x.Registrar = "" + case "fairyring.pep.ContractDetails.contract_address": + x.ContractAddress = "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ContractDetails")) + } + panic(fmt.Errorf("message fairyring.pep.ContractDetails does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_ContractDetails) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "fairyring.pep.ContractDetails.registrar": + value := x.Registrar + return protoreflect.ValueOfString(value) + case "fairyring.pep.ContractDetails.contract_address": + value := x.ContractAddress + return protoreflect.ValueOfString(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ContractDetails")) + } + panic(fmt.Errorf("message fairyring.pep.ContractDetails does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ContractDetails) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "fairyring.pep.ContractDetails.registrar": + x.Registrar = value.Interface().(string) + case "fairyring.pep.ContractDetails.contract_address": + x.ContractAddress = value.Interface().(string) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ContractDetails")) + } + panic(fmt.Errorf("message fairyring.pep.ContractDetails does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ContractDetails) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.ContractDetails.registrar": + panic(fmt.Errorf("field registrar of message fairyring.pep.ContractDetails is not mutable")) + case "fairyring.pep.ContractDetails.contract_address": + panic(fmt.Errorf("field contract_address of message fairyring.pep.ContractDetails is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ContractDetails")) + } + panic(fmt.Errorf("message fairyring.pep.ContractDetails does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_ContractDetails) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.ContractDetails.registrar": + return protoreflect.ValueOfString("") + case "fairyring.pep.ContractDetails.contract_address": + return protoreflect.ValueOfString("") + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ContractDetails")) + } + panic(fmt.Errorf("message fairyring.pep.ContractDetails does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_ContractDetails) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in fairyring.pep.ContractDetails", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_ContractDetails) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ContractDetails) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_ContractDetails) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_ContractDetails) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*ContractDetails) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.Registrar) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.ContractAddress) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*ContractDetails) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.ContractAddress) > 0 { + i -= len(x.ContractAddress) + copy(dAtA[i:], x.ContractAddress) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ContractAddress))) + i-- + dAtA[i] = 0x12 + } + if len(x.Registrar) > 0 { + i -= len(x.Registrar) + copy(dAtA[i:], x.Registrar) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Registrar))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*ContractDetails) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ContractDetails: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ContractDetails: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Registrar", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Registrar = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.ContractAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var _ protoreflect.List = (*_RegisterdContract_2_list)(nil) + +type _RegisterdContract_2_list struct { + list *[]*ContractDetails +} + +func (x *_RegisterdContract_2_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_RegisterdContract_2_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfMessage((*x.list)[i].ProtoReflect()) +} + +func (x *_RegisterdContract_2_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.Message() + concreteValue := valueUnwrapped.Interface().(*ContractDetails) + (*x.list)[i] = concreteValue +} + +func (x *_RegisterdContract_2_list) Append(value protoreflect.Value) { + valueUnwrapped := value.Message() + concreteValue := valueUnwrapped.Interface().(*ContractDetails) + *x.list = append(*x.list, concreteValue) +} + +func (x *_RegisterdContract_2_list) AppendMutable() protoreflect.Value { + v := new(ContractDetails) + *x.list = append(*x.list, v) + return protoreflect.ValueOfMessage(v.ProtoReflect()) +} + +func (x *_RegisterdContract_2_list) Truncate(n int) { + for i := n; i < len(*x.list); i++ { + (*x.list)[i] = nil + } + *x.list = (*x.list)[:n] +} + +func (x *_RegisterdContract_2_list) NewElement() protoreflect.Value { + v := new(ContractDetails) + return protoreflect.ValueOfMessage(v.ProtoReflect()) +} + +func (x *_RegisterdContract_2_list) IsValid() bool { + return x.list != nil +} + +var ( + md_RegisterdContract protoreflect.MessageDescriptor + fd_RegisterdContract_identity protoreflect.FieldDescriptor + fd_RegisterdContract_contracts protoreflect.FieldDescriptor +) + +func init() { + file_fairyring_pep_request_id_proto_init() + md_RegisterdContract = File_fairyring_pep_request_id_proto.Messages().ByName("RegisterdContract") + fd_RegisterdContract_identity = md_RegisterdContract.Fields().ByName("identity") + fd_RegisterdContract_contracts = md_RegisterdContract.Fields().ByName("contracts") +} + +var _ protoreflect.Message = (*fastReflection_RegisterdContract)(nil) + +type fastReflection_RegisterdContract RegisterdContract + +func (x *RegisterdContract) ProtoReflect() protoreflect.Message { + return (*fastReflection_RegisterdContract)(x) +} + +func (x *RegisterdContract) slowProtoReflect() protoreflect.Message { + mi := &file_fairyring_pep_request_id_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_RegisterdContract_messageType fastReflection_RegisterdContract_messageType +var _ protoreflect.MessageType = fastReflection_RegisterdContract_messageType{} + +type fastReflection_RegisterdContract_messageType struct{} + +func (x fastReflection_RegisterdContract_messageType) Zero() protoreflect.Message { + return (*fastReflection_RegisterdContract)(nil) +} +func (x fastReflection_RegisterdContract_messageType) New() protoreflect.Message { + return new(fastReflection_RegisterdContract) +} +func (x fastReflection_RegisterdContract_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_RegisterdContract +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_RegisterdContract) Descriptor() protoreflect.MessageDescriptor { + return md_RegisterdContract +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_RegisterdContract) Type() protoreflect.MessageType { + return _fastReflection_RegisterdContract_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_RegisterdContract) New() protoreflect.Message { + return new(fastReflection_RegisterdContract) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_RegisterdContract) Interface() protoreflect.ProtoMessage { + return (*RegisterdContract)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_RegisterdContract) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Identity != "" { + value := protoreflect.ValueOfString(x.Identity) + if !f(fd_RegisterdContract_identity, value) { + return + } + } + if len(x.Contracts) != 0 { + value := protoreflect.ValueOfList(&_RegisterdContract_2_list{list: &x.Contracts}) + if !f(fd_RegisterdContract_contracts, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_RegisterdContract) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "fairyring.pep.RegisterdContract.identity": + return x.Identity != "" + case "fairyring.pep.RegisterdContract.contracts": + return len(x.Contracts) != 0 + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + } + panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_RegisterdContract) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "fairyring.pep.RegisterdContract.identity": + x.Identity = "" + case "fairyring.pep.RegisterdContract.contracts": + x.Contracts = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + } + panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_RegisterdContract) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "fairyring.pep.RegisterdContract.identity": + value := x.Identity + return protoreflect.ValueOfString(value) + case "fairyring.pep.RegisterdContract.contracts": + if len(x.Contracts) == 0 { + return protoreflect.ValueOfList(&_RegisterdContract_2_list{}) + } + listValue := &_RegisterdContract_2_list{list: &x.Contracts} + return protoreflect.ValueOfList(listValue) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + } + panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_RegisterdContract) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "fairyring.pep.RegisterdContract.identity": + x.Identity = value.Interface().(string) + case "fairyring.pep.RegisterdContract.contracts": + lv := value.List() + clv := lv.(*_RegisterdContract_2_list) + x.Contracts = *clv.list + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + } + panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_RegisterdContract) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.RegisterdContract.contracts": + if x.Contracts == nil { + x.Contracts = []*ContractDetails{} + } + value := &_RegisterdContract_2_list{list: &x.Contracts} + return protoreflect.ValueOfList(value) + case "fairyring.pep.RegisterdContract.identity": + panic(fmt.Errorf("field identity of message fairyring.pep.RegisterdContract is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + } + panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_RegisterdContract) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.RegisterdContract.identity": + return protoreflect.ValueOfString("") + case "fairyring.pep.RegisterdContract.contracts": + list := []*ContractDetails{} + return protoreflect.ValueOfList(&_RegisterdContract_2_list{list: &list}) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + } + panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_RegisterdContract) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in fairyring.pep.RegisterdContract", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_RegisterdContract) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_RegisterdContract) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_RegisterdContract) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_RegisterdContract) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*RegisterdContract) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.Identity) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if len(x.Contracts) > 0 { + for _, e := range x.Contracts { + l = options.Size(e) + n += 1 + l + runtime.Sov(uint64(l)) + } + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*RegisterdContract) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.Contracts) > 0 { + for iNdEx := len(x.Contracts) - 1; iNdEx >= 0; iNdEx-- { + encoded, err := options.Marshal(x.Contracts[iNdEx]) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x12 + } + } + if len(x.Identity) > 0 { + i -= len(x.Identity) + copy(dAtA[i:], x.Identity) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Identity))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*RegisterdContract) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: RegisterdContract: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: RegisterdContract: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Identity", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Identity = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Contracts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Contracts = append(x.Contracts, &ContractDetails{}) + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Contracts[len(x.Contracts)-1]); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_ExecuteContractMsg protoreflect.MessageDescriptor + fd_ExecuteContractMsg_identity protoreflect.FieldDescriptor + fd_ExecuteContractMsg_pubkey protoreflect.FieldDescriptor + fd_ExecuteContractMsg_aggr_keyshare protoreflect.FieldDescriptor +) + +func init() { + file_fairyring_pep_request_id_proto_init() + md_ExecuteContractMsg = File_fairyring_pep_request_id_proto.Messages().ByName("ExecuteContractMsg") + fd_ExecuteContractMsg_identity = md_ExecuteContractMsg.Fields().ByName("identity") + fd_ExecuteContractMsg_pubkey = md_ExecuteContractMsg.Fields().ByName("pubkey") + fd_ExecuteContractMsg_aggr_keyshare = md_ExecuteContractMsg.Fields().ByName("aggr_keyshare") +} + +var _ protoreflect.Message = (*fastReflection_ExecuteContractMsg)(nil) + +type fastReflection_ExecuteContractMsg ExecuteContractMsg + +func (x *ExecuteContractMsg) ProtoReflect() protoreflect.Message { + return (*fastReflection_ExecuteContractMsg)(x) +} + +func (x *ExecuteContractMsg) slowProtoReflect() protoreflect.Message { + mi := &file_fairyring_pep_request_id_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_ExecuteContractMsg_messageType fastReflection_ExecuteContractMsg_messageType +var _ protoreflect.MessageType = fastReflection_ExecuteContractMsg_messageType{} + +type fastReflection_ExecuteContractMsg_messageType struct{} + +func (x fastReflection_ExecuteContractMsg_messageType) Zero() protoreflect.Message { + return (*fastReflection_ExecuteContractMsg)(nil) +} +func (x fastReflection_ExecuteContractMsg_messageType) New() protoreflect.Message { + return new(fastReflection_ExecuteContractMsg) +} +func (x fastReflection_ExecuteContractMsg_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_ExecuteContractMsg +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_ExecuteContractMsg) Descriptor() protoreflect.MessageDescriptor { + return md_ExecuteContractMsg +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_ExecuteContractMsg) Type() protoreflect.MessageType { + return _fastReflection_ExecuteContractMsg_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_ExecuteContractMsg) New() protoreflect.Message { + return new(fastReflection_ExecuteContractMsg) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_ExecuteContractMsg) Interface() protoreflect.ProtoMessage { + return (*ExecuteContractMsg)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_ExecuteContractMsg) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Identity != "" { + value := protoreflect.ValueOfString(x.Identity) + if !f(fd_ExecuteContractMsg_identity, value) { + return + } + } + if x.Pubkey != "" { + value := protoreflect.ValueOfString(x.Pubkey) + if !f(fd_ExecuteContractMsg_pubkey, value) { + return + } + } + if x.AggrKeyshare != "" { + value := protoreflect.ValueOfString(x.AggrKeyshare) + if !f(fd_ExecuteContractMsg_aggr_keyshare, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_ExecuteContractMsg) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "fairyring.pep.ExecuteContractMsg.identity": + return x.Identity != "" + case "fairyring.pep.ExecuteContractMsg.pubkey": + return x.Pubkey != "" + case "fairyring.pep.ExecuteContractMsg.aggr_keyshare": + return x.AggrKeyshare != "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ExecuteContractMsg")) + } + panic(fmt.Errorf("message fairyring.pep.ExecuteContractMsg does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ExecuteContractMsg) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "fairyring.pep.ExecuteContractMsg.identity": + x.Identity = "" + case "fairyring.pep.ExecuteContractMsg.pubkey": + x.Pubkey = "" + case "fairyring.pep.ExecuteContractMsg.aggr_keyshare": + x.AggrKeyshare = "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ExecuteContractMsg")) + } + panic(fmt.Errorf("message fairyring.pep.ExecuteContractMsg does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_ExecuteContractMsg) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "fairyring.pep.ExecuteContractMsg.identity": + value := x.Identity + return protoreflect.ValueOfString(value) + case "fairyring.pep.ExecuteContractMsg.pubkey": + value := x.Pubkey + return protoreflect.ValueOfString(value) + case "fairyring.pep.ExecuteContractMsg.aggr_keyshare": + value := x.AggrKeyshare + return protoreflect.ValueOfString(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ExecuteContractMsg")) + } + panic(fmt.Errorf("message fairyring.pep.ExecuteContractMsg does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ExecuteContractMsg) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "fairyring.pep.ExecuteContractMsg.identity": + x.Identity = value.Interface().(string) + case "fairyring.pep.ExecuteContractMsg.pubkey": + x.Pubkey = value.Interface().(string) + case "fairyring.pep.ExecuteContractMsg.aggr_keyshare": + x.AggrKeyshare = value.Interface().(string) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ExecuteContractMsg")) + } + panic(fmt.Errorf("message fairyring.pep.ExecuteContractMsg does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ExecuteContractMsg) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.ExecuteContractMsg.identity": + panic(fmt.Errorf("field identity of message fairyring.pep.ExecuteContractMsg is not mutable")) + case "fairyring.pep.ExecuteContractMsg.pubkey": + panic(fmt.Errorf("field pubkey of message fairyring.pep.ExecuteContractMsg is not mutable")) + case "fairyring.pep.ExecuteContractMsg.aggr_keyshare": + panic(fmt.Errorf("field aggr_keyshare of message fairyring.pep.ExecuteContractMsg is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ExecuteContractMsg")) + } + panic(fmt.Errorf("message fairyring.pep.ExecuteContractMsg does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_ExecuteContractMsg) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.ExecuteContractMsg.identity": + return protoreflect.ValueOfString("") + case "fairyring.pep.ExecuteContractMsg.pubkey": + return protoreflect.ValueOfString("") + case "fairyring.pep.ExecuteContractMsg.aggr_keyshare": + return protoreflect.ValueOfString("") + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.ExecuteContractMsg")) + } + panic(fmt.Errorf("message fairyring.pep.ExecuteContractMsg does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_ExecuteContractMsg) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in fairyring.pep.ExecuteContractMsg", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_ExecuteContractMsg) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ExecuteContractMsg) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_ExecuteContractMsg) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_ExecuteContractMsg) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*ExecuteContractMsg) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.Identity) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.Pubkey) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.AggrKeyshare) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*ExecuteContractMsg) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.AggrKeyshare) > 0 { + i -= len(x.AggrKeyshare) + copy(dAtA[i:], x.AggrKeyshare) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.AggrKeyshare))) + i-- + dAtA[i] = 0x1a + } + if len(x.Pubkey) > 0 { + i -= len(x.Pubkey) + copy(dAtA[i:], x.Pubkey) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Pubkey))) + i-- + dAtA[i] = 0x12 + } + if len(x.Identity) > 0 { + i -= len(x.Identity) + copy(dAtA[i:], x.Identity) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Identity))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*ExecuteContractMsg) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExecuteContractMsg: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExecuteContractMsg: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Identity", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Identity = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Pubkey", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Pubkey = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field AggrKeyshare", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.AggrKeyshare = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -1299,6 +2889,143 @@ func (x *PrivateRequest) GetEncryptedKeyshares() []*common.EncryptedKeyshare { return nil } +type ContractDetails struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Registrar string `protobuf:"bytes,1,opt,name=registrar,proto3" json:"registrar,omitempty"` + ContractAddress string `protobuf:"bytes,2,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"` +} + +func (x *ContractDetails) Reset() { + *x = ContractDetails{} + if protoimpl.UnsafeEnabled { + mi := &file_fairyring_pep_request_id_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ContractDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ContractDetails) ProtoMessage() {} + +// Deprecated: Use ContractDetails.ProtoReflect.Descriptor instead. +func (*ContractDetails) Descriptor() ([]byte, []int) { + return file_fairyring_pep_request_id_proto_rawDescGZIP(), []int{2} +} + +func (x *ContractDetails) GetRegistrar() string { + if x != nil { + return x.Registrar + } + return "" +} + +func (x *ContractDetails) GetContractAddress() string { + if x != nil { + return x.ContractAddress + } + return "" +} + +type RegisterdContract struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + Contracts []*ContractDetails `protobuf:"bytes,2,rep,name=contracts,proto3" json:"contracts,omitempty"` +} + +func (x *RegisterdContract) Reset() { + *x = RegisterdContract{} + if protoimpl.UnsafeEnabled { + mi := &file_fairyring_pep_request_id_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterdContract) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterdContract) ProtoMessage() {} + +// Deprecated: Use RegisterdContract.ProtoReflect.Descriptor instead. +func (*RegisterdContract) Descriptor() ([]byte, []int) { + return file_fairyring_pep_request_id_proto_rawDescGZIP(), []int{3} +} + +func (x *RegisterdContract) GetIdentity() string { + if x != nil { + return x.Identity + } + return "" +} + +func (x *RegisterdContract) GetContracts() []*ContractDetails { + if x != nil { + return x.Contracts + } + return nil +} + +type ExecuteContractMsg struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + Pubkey string `protobuf:"bytes,2,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + AggrKeyshare string `protobuf:"bytes,3,opt,name=aggr_keyshare,json=aggrKeyshare,proto3" json:"aggr_keyshare,omitempty"` +} + +func (x *ExecuteContractMsg) Reset() { + *x = ExecuteContractMsg{} + if protoimpl.UnsafeEnabled { + mi := &file_fairyring_pep_request_id_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteContractMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteContractMsg) ProtoMessage() {} + +// Deprecated: Use ExecuteContractMsg.ProtoReflect.Descriptor instead. +func (*ExecuteContractMsg) Descriptor() ([]byte, []int) { + return file_fairyring_pep_request_id_proto_rawDescGZIP(), []int{4} +} + +func (x *ExecuteContractMsg) GetIdentity() string { + if x != nil { + return x.Identity + } + return "" +} + +func (x *ExecuteContractMsg) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *ExecuteContractMsg) GetAggrKeyshare() string { + if x != nil { + return x.AggrKeyshare + } + return "" +} + var File_fairyring_pep_request_id_proto protoreflect.FileDescriptor var file_fairyring_pep_request_id_proto_rawDesc = []byte{ @@ -1323,17 +3050,37 @@ var file_fairyring_pep_request_id_proto_rawDesc = []byte{ 0x32, 0x23, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x12, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, - 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x42, 0x98, 0x01, 0x0a, 0x11, 0x63, 0x6f, - 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x42, - 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, - 0x70, 0xa2, 0x02, 0x03, 0x46, 0x50, 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, - 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, - 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, - 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, - 0x3a, 0x50, 0x65, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x22, 0x5a, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1c, 0x0a, 0x09, + 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x6d, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x66, 0x61, 0x69, 0x72, + 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x73, 0x22, 0x6d, 0x0a, 0x12, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x4d, 0x73, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, + 0x0a, 0x0d, 0x61, 0x67, 0x67, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x67, 0x67, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x68, + 0x61, 0x72, 0x65, 0x42, 0x98, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, + 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x42, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x49, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x61, + 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0xa2, 0x02, 0x03, 0x46, 0x50, + 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, + 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, + 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, + 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, + 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x50, 0x65, 0x70, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1348,19 +3095,23 @@ func file_fairyring_pep_request_id_proto_rawDescGZIP() []byte { return file_fairyring_pep_request_id_proto_rawDescData } -var file_fairyring_pep_request_id_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_fairyring_pep_request_id_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_fairyring_pep_request_id_proto_goTypes = []interface{}{ (*RequestId)(nil), // 0: fairyring.pep.RequestId (*PrivateRequest)(nil), // 1: fairyring.pep.PrivateRequest - (*common.EncryptedKeyshare)(nil), // 2: fairyring.common.EncryptedKeyshare + (*ContractDetails)(nil), // 2: fairyring.pep.ContractDetails + (*RegisterdContract)(nil), // 3: fairyring.pep.RegisterdContract + (*ExecuteContractMsg)(nil), // 4: fairyring.pep.ExecuteContractMsg + (*common.EncryptedKeyshare)(nil), // 5: fairyring.common.EncryptedKeyshare } var file_fairyring_pep_request_id_proto_depIdxs = []int32{ - 2, // 0: fairyring.pep.PrivateRequest.encrypted_keyshares:type_name -> fairyring.common.EncryptedKeyshare - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name + 5, // 0: fairyring.pep.PrivateRequest.encrypted_keyshares:type_name -> fairyring.common.EncryptedKeyshare + 2, // 1: fairyring.pep.RegisterdContract.contracts:type_name -> fairyring.pep.ContractDetails + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_fairyring_pep_request_id_proto_init() } @@ -1393,6 +3144,42 @@ func file_fairyring_pep_request_id_proto_init() { return nil } } + file_fairyring_pep_request_id_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ContractDetails); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fairyring_pep_request_id_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterdContract); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fairyring_pep_request_id_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteContractMsg); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1400,7 +3187,7 @@ func file_fairyring_pep_request_id_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_fairyring_pep_request_id_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 5, NumExtensions: 0, NumServices: 0, }, diff --git a/api/fairyring/pep/tx.pulsar.go b/api/fairyring/pep/tx.pulsar.go index e1d052aa..9437a91a 100644 --- a/api/fairyring/pep/tx.pulsar.go +++ b/api/fairyring/pep/tx.pulsar.go @@ -6828,6 +6828,910 @@ func (x *fastReflection_MsgGetPrivateKeysharesResponse) ProtoMethods() *protoifa } } +var ( + md_MsgRegisterContract protoreflect.MessageDescriptor + fd_MsgRegisterContract_creator protoreflect.FieldDescriptor + fd_MsgRegisterContract_contract_address protoreflect.FieldDescriptor + fd_MsgRegisterContract_identity protoreflect.FieldDescriptor +) + +func init() { + file_fairyring_pep_tx_proto_init() + md_MsgRegisterContract = File_fairyring_pep_tx_proto.Messages().ByName("MsgRegisterContract") + fd_MsgRegisterContract_creator = md_MsgRegisterContract.Fields().ByName("creator") + fd_MsgRegisterContract_contract_address = md_MsgRegisterContract.Fields().ByName("contract_address") + fd_MsgRegisterContract_identity = md_MsgRegisterContract.Fields().ByName("identity") +} + +var _ protoreflect.Message = (*fastReflection_MsgRegisterContract)(nil) + +type fastReflection_MsgRegisterContract MsgRegisterContract + +func (x *MsgRegisterContract) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgRegisterContract)(x) +} + +func (x *MsgRegisterContract) slowProtoReflect() protoreflect.Message { + mi := &file_fairyring_pep_tx_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_MsgRegisterContract_messageType fastReflection_MsgRegisterContract_messageType +var _ protoreflect.MessageType = fastReflection_MsgRegisterContract_messageType{} + +type fastReflection_MsgRegisterContract_messageType struct{} + +func (x fastReflection_MsgRegisterContract_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgRegisterContract)(nil) +} +func (x fastReflection_MsgRegisterContract_messageType) New() protoreflect.Message { + return new(fastReflection_MsgRegisterContract) +} +func (x fastReflection_MsgRegisterContract_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgRegisterContract +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgRegisterContract) Descriptor() protoreflect.MessageDescriptor { + return md_MsgRegisterContract +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_MsgRegisterContract) Type() protoreflect.MessageType { + return _fastReflection_MsgRegisterContract_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgRegisterContract) New() protoreflect.Message { + return new(fastReflection_MsgRegisterContract) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgRegisterContract) Interface() protoreflect.ProtoMessage { + return (*MsgRegisterContract)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_MsgRegisterContract) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Creator != "" { + value := protoreflect.ValueOfString(x.Creator) + if !f(fd_MsgRegisterContract_creator, value) { + return + } + } + if x.ContractAddress != "" { + value := protoreflect.ValueOfString(x.ContractAddress) + if !f(fd_MsgRegisterContract_contract_address, value) { + return + } + } + if x.Identity != "" { + value := protoreflect.ValueOfString(x.Identity) + if !f(fd_MsgRegisterContract_identity, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_MsgRegisterContract) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "fairyring.pep.MsgRegisterContract.creator": + return x.Creator != "" + case "fairyring.pep.MsgRegisterContract.contract_address": + return x.ContractAddress != "" + case "fairyring.pep.MsgRegisterContract.identity": + return x.Identity != "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContract does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRegisterContract) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "fairyring.pep.MsgRegisterContract.creator": + x.Creator = "" + case "fairyring.pep.MsgRegisterContract.contract_address": + x.ContractAddress = "" + case "fairyring.pep.MsgRegisterContract.identity": + x.Identity = "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContract does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_MsgRegisterContract) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "fairyring.pep.MsgRegisterContract.creator": + value := x.Creator + return protoreflect.ValueOfString(value) + case "fairyring.pep.MsgRegisterContract.contract_address": + value := x.ContractAddress + return protoreflect.ValueOfString(value) + case "fairyring.pep.MsgRegisterContract.identity": + value := x.Identity + return protoreflect.ValueOfString(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContract does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRegisterContract) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "fairyring.pep.MsgRegisterContract.creator": + x.Creator = value.Interface().(string) + case "fairyring.pep.MsgRegisterContract.contract_address": + x.ContractAddress = value.Interface().(string) + case "fairyring.pep.MsgRegisterContract.identity": + x.Identity = value.Interface().(string) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContract does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRegisterContract) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.MsgRegisterContract.creator": + panic(fmt.Errorf("field creator of message fairyring.pep.MsgRegisterContract is not mutable")) + case "fairyring.pep.MsgRegisterContract.contract_address": + panic(fmt.Errorf("field contract_address of message fairyring.pep.MsgRegisterContract is not mutable")) + case "fairyring.pep.MsgRegisterContract.identity": + panic(fmt.Errorf("field identity of message fairyring.pep.MsgRegisterContract is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContract does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_MsgRegisterContract) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.MsgRegisterContract.creator": + return protoreflect.ValueOfString("") + case "fairyring.pep.MsgRegisterContract.contract_address": + return protoreflect.ValueOfString("") + case "fairyring.pep.MsgRegisterContract.identity": + return protoreflect.ValueOfString("") + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContract does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_MsgRegisterContract) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in fairyring.pep.MsgRegisterContract", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_MsgRegisterContract) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRegisterContract) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_MsgRegisterContract) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_MsgRegisterContract) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgRegisterContract) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.Creator) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.ContractAddress) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.Identity) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*MsgRegisterContract) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.Identity) > 0 { + i -= len(x.Identity) + copy(dAtA[i:], x.Identity) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Identity))) + i-- + dAtA[i] = 0x1a + } + if len(x.ContractAddress) > 0 { + i -= len(x.ContractAddress) + copy(dAtA[i:], x.ContractAddress) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ContractAddress))) + i-- + dAtA[i] = 0x12 + } + if len(x.Creator) > 0 { + i -= len(x.Creator) + copy(dAtA[i:], x.Creator) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Creator))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*MsgRegisterContract) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgRegisterContract: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgRegisterContract: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.ContractAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Identity", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Identity = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_MsgRegisterContractResponse protoreflect.MessageDescriptor +) + +func init() { + file_fairyring_pep_tx_proto_init() + md_MsgRegisterContractResponse = File_fairyring_pep_tx_proto.Messages().ByName("MsgRegisterContractResponse") +} + +var _ protoreflect.Message = (*fastReflection_MsgRegisterContractResponse)(nil) + +type fastReflection_MsgRegisterContractResponse MsgRegisterContractResponse + +func (x *MsgRegisterContractResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgRegisterContractResponse)(x) +} + +func (x *MsgRegisterContractResponse) slowProtoReflect() protoreflect.Message { + mi := &file_fairyring_pep_tx_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_MsgRegisterContractResponse_messageType fastReflection_MsgRegisterContractResponse_messageType +var _ protoreflect.MessageType = fastReflection_MsgRegisterContractResponse_messageType{} + +type fastReflection_MsgRegisterContractResponse_messageType struct{} + +func (x fastReflection_MsgRegisterContractResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgRegisterContractResponse)(nil) +} +func (x fastReflection_MsgRegisterContractResponse_messageType) New() protoreflect.Message { + return new(fastReflection_MsgRegisterContractResponse) +} +func (x fastReflection_MsgRegisterContractResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgRegisterContractResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgRegisterContractResponse) Descriptor() protoreflect.MessageDescriptor { + return md_MsgRegisterContractResponse +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_MsgRegisterContractResponse) Type() protoreflect.MessageType { + return _fastReflection_MsgRegisterContractResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgRegisterContractResponse) New() protoreflect.Message { + return new(fastReflection_MsgRegisterContractResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgRegisterContractResponse) Interface() protoreflect.ProtoMessage { + return (*MsgRegisterContractResponse)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_MsgRegisterContractResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_MsgRegisterContractResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRegisterContractResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_MsgRegisterContractResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContractResponse does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRegisterContractResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRegisterContractResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_MsgRegisterContractResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgRegisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgRegisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_MsgRegisterContractResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in fairyring.pep.MsgRegisterContractResponse", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_MsgRegisterContractResponse) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRegisterContractResponse) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_MsgRegisterContractResponse) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_MsgRegisterContractResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgRegisterContractResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*MsgRegisterContractResponse) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*MsgRegisterContractResponse) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgRegisterContractResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgRegisterContractResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -7431,6 +8335,83 @@ func (*MsgGetPrivateKeysharesResponse) Descriptor() ([]byte, []int) { return file_fairyring_pep_tx_proto_rawDescGZIP(), []int{14} } +type MsgRegisterContract struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + ContractAddress string `protobuf:"bytes,2,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"` + Identity string `protobuf:"bytes,3,opt,name=identity,proto3" json:"identity,omitempty"` +} + +func (x *MsgRegisterContract) Reset() { + *x = MsgRegisterContract{} + if protoimpl.UnsafeEnabled { + mi := &file_fairyring_pep_tx_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgRegisterContract) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgRegisterContract) ProtoMessage() {} + +// Deprecated: Use MsgRegisterContract.ProtoReflect.Descriptor instead. +func (*MsgRegisterContract) Descriptor() ([]byte, []int) { + return file_fairyring_pep_tx_proto_rawDescGZIP(), []int{15} +} + +func (x *MsgRegisterContract) GetCreator() string { + if x != nil { + return x.Creator + } + return "" +} + +func (x *MsgRegisterContract) GetContractAddress() string { + if x != nil { + return x.ContractAddress + } + return "" +} + +func (x *MsgRegisterContract) GetIdentity() string { + if x != nil { + return x.Identity + } + return "" +} + +type MsgRegisterContractResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *MsgRegisterContractResponse) Reset() { + *x = MsgRegisterContractResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_fairyring_pep_tx_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgRegisterContractResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgRegisterContractResponse) ProtoMessage() {} + +// Deprecated: Use MsgRegisterContractResponse.ProtoReflect.Descriptor instead. +func (*MsgRegisterContractResponse) Descriptor() ([]byte, []int) { + return file_fairyring_pep_tx_proto_rawDescGZIP(), []int{16} +} + var File_fairyring_pep_tx_proto protoreflect.FileDescriptor var file_fairyring_pep_tx_proto_rawDesc = []byte{ @@ -7533,72 +8514,89 @@ var file_fairyring_pep_tx_proto_rawDesc = []byte{ 0x79, 0x3a, 0x0c, 0x82, 0xe7, 0xb0, 0x2a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x20, 0x0a, 0x1e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x32, 0xff, 0x06, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x56, 0x0a, 0x0c, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1e, 0x2e, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x65, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x12, 0x23, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, + 0x65, 0x22, 0x84, 0x01, 0x0a, 0x13, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, 0x0c, 0x82, 0xe7, 0xb0, 0x2a, + 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x1d, 0x0a, 0x1b, 0x4d, 0x73, 0x67, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe3, 0x07, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, + 0x56, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, + 0x1e, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, + 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, + 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, + 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x12, 0x23, 0x2e, 0x66, + 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, + 0x78, 0x1a, 0x2b, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, + 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, + 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x45, + 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x12, 0x2a, 0x2e, 0x66, 0x61, 0x69, + 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x1a, 0x2b, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x1a, 0x2b, 0x2e, 0x66, 0x61, - 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x65, 0x64, 0x54, 0x78, 0x12, 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, - 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, - 0x1a, 0x2b, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, - 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, - 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x64, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x12, 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, - 0x53, 0x68, 0x61, 0x72, 0x65, 0x1a, 0x32, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, - 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x16, 0x52, 0x65, 0x71, + 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x12, + 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, + 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x1a, 0x32, 0x2e, 0x66, 0x61, + 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, + 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x74, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0x28, 0x2e, 0x66, 0x61, 0x69, 0x72, + 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, - 0x61, 0x72, 0x65, 0x12, 0x28, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x72, 0x65, 0x1a, 0x30, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x1a, 0x30, 0x2e, - 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, - 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x68, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, - 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0x24, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, - 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x1a, 0x2c, 0x2e, 0x66, 0x61, + 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0x24, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x16, 0x52, 0x65, 0x71, + 0x65, 0x1a, 0x2c, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, + 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, + 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x74, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x28, 0x2e, 0x66, 0x61, 0x69, 0x72, + 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x12, 0x28, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x69, 0x74, 0x79, 0x1a, 0x30, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x30, 0x2e, - 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x6b, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, - 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x1a, 0x2d, 0x2e, - 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, - 0x67, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, - 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, - 0xb0, 0x2a, 0x01, 0x42, 0x91, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, - 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, - 0x2f, 0x70, 0x65, 0x70, 0xa2, 0x02, 0x03, 0x46, 0x50, 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, - 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, - 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, - 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, - 0x6e, 0x67, 0x3a, 0x3a, 0x50, 0x65, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x66, + 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, + 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, + 0x72, 0x65, 0x73, 0x1a, 0x2d, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x62, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x22, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, + 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x1a, 0x2a, 0x2e, 0x66, 0x61, 0x69, + 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, 0x2a, 0x01, 0x42, 0x91, 0x01, + 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x70, 0x65, 0x70, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0xa2, 0x02, + 0x03, 0x46, 0x50, 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x2e, 0x50, 0x65, 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x5c, 0x50, 0x65, 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x5c, 0x50, 0x65, 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x0e, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x50, 0x65, + 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -7613,7 +8611,7 @@ func file_fairyring_pep_tx_proto_rawDescGZIP() []byte { return file_fairyring_pep_tx_proto_rawDescData } -var file_fairyring_pep_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_fairyring_pep_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_fairyring_pep_tx_proto_goTypes = []interface{}{ (*MsgUpdateParams)(nil), // 0: fairyring.pep.MsgUpdateParams (*MsgUpdateParamsResponse)(nil), // 1: fairyring.pep.MsgUpdateParamsResponse @@ -7630,12 +8628,14 @@ var file_fairyring_pep_tx_proto_goTypes = []interface{}{ (*MsgRequestPrivateIdentityResponse)(nil), // 12: fairyring.pep.MsgRequestPrivateIdentityResponse (*MsgGetPrivateKeyshares)(nil), // 13: fairyring.pep.MsgGetPrivateKeyshares (*MsgGetPrivateKeysharesResponse)(nil), // 14: fairyring.pep.MsgGetPrivateKeysharesResponse - (*Params)(nil), // 15: fairyring.pep.Params - (*durationpb.Duration)(nil), // 16: google.protobuf.Duration + (*MsgRegisterContract)(nil), // 15: fairyring.pep.MsgRegisterContract + (*MsgRegisterContractResponse)(nil), // 16: fairyring.pep.MsgRegisterContractResponse + (*Params)(nil), // 17: fairyring.pep.Params + (*durationpb.Duration)(nil), // 18: google.protobuf.Duration } var file_fairyring_pep_tx_proto_depIdxs = []int32{ - 15, // 0: fairyring.pep.MsgUpdateParams.params:type_name -> fairyring.pep.Params - 16, // 1: fairyring.pep.MsgRequestGeneralKeyshare.estimated_delay:type_name -> google.protobuf.Duration + 17, // 0: fairyring.pep.MsgUpdateParams.params:type_name -> fairyring.pep.Params + 18, // 1: fairyring.pep.MsgRequestGeneralKeyshare.estimated_delay:type_name -> google.protobuf.Duration 0, // 2: fairyring.pep.Msg.UpdateParams:input_type -> fairyring.pep.MsgUpdateParams 2, // 3: fairyring.pep.Msg.SubmitEncryptedTx:input_type -> fairyring.pep.MsgSubmitEncryptedTx 3, // 4: fairyring.pep.Msg.SubmitGeneralEncryptedTx:input_type -> fairyring.pep.MsgSubmitGeneralEncryptedTx @@ -7644,16 +8644,18 @@ var file_fairyring_pep_tx_proto_depIdxs = []int32{ 9, // 7: fairyring.pep.Msg.GetGeneralKeyshare:input_type -> fairyring.pep.MsgGetGeneralKeyshare 11, // 8: fairyring.pep.Msg.RequestPrivateIdentity:input_type -> fairyring.pep.MsgRequestPrivateIdentity 13, // 9: fairyring.pep.Msg.GetPrivateKeyshares:input_type -> fairyring.pep.MsgGetPrivateKeyshares - 1, // 10: fairyring.pep.Msg.UpdateParams:output_type -> fairyring.pep.MsgUpdateParamsResponse - 4, // 11: fairyring.pep.Msg.SubmitEncryptedTx:output_type -> fairyring.pep.MsgSubmitEncryptedTxResponse - 4, // 12: fairyring.pep.Msg.SubmitGeneralEncryptedTx:output_type -> fairyring.pep.MsgSubmitEncryptedTxResponse - 6, // 13: fairyring.pep.Msg.CreateAggregatedKeyShare:output_type -> fairyring.pep.MsgCreateAggregatedKeyShareResponse - 8, // 14: fairyring.pep.Msg.RequestGeneralKeyshare:output_type -> fairyring.pep.MsgRequestGeneralKeyshareResponse - 10, // 15: fairyring.pep.Msg.GetGeneralKeyshare:output_type -> fairyring.pep.MsgGetGeneralKeyshareResponse - 12, // 16: fairyring.pep.Msg.RequestPrivateIdentity:output_type -> fairyring.pep.MsgRequestPrivateIdentityResponse - 14, // 17: fairyring.pep.Msg.GetPrivateKeyshares:output_type -> fairyring.pep.MsgGetPrivateKeysharesResponse - 10, // [10:18] is the sub-list for method output_type - 2, // [2:10] is the sub-list for method input_type + 15, // 10: fairyring.pep.Msg.RegisterContract:input_type -> fairyring.pep.MsgRegisterContract + 1, // 11: fairyring.pep.Msg.UpdateParams:output_type -> fairyring.pep.MsgUpdateParamsResponse + 4, // 12: fairyring.pep.Msg.SubmitEncryptedTx:output_type -> fairyring.pep.MsgSubmitEncryptedTxResponse + 4, // 13: fairyring.pep.Msg.SubmitGeneralEncryptedTx:output_type -> fairyring.pep.MsgSubmitEncryptedTxResponse + 6, // 14: fairyring.pep.Msg.CreateAggregatedKeyShare:output_type -> fairyring.pep.MsgCreateAggregatedKeyShareResponse + 8, // 15: fairyring.pep.Msg.RequestGeneralKeyshare:output_type -> fairyring.pep.MsgRequestGeneralKeyshareResponse + 10, // 16: fairyring.pep.Msg.GetGeneralKeyshare:output_type -> fairyring.pep.MsgGetGeneralKeyshareResponse + 12, // 17: fairyring.pep.Msg.RequestPrivateIdentity:output_type -> fairyring.pep.MsgRequestPrivateIdentityResponse + 14, // 18: fairyring.pep.Msg.GetPrivateKeyshares:output_type -> fairyring.pep.MsgGetPrivateKeysharesResponse + 16, // 19: fairyring.pep.Msg.RegisterContract:output_type -> fairyring.pep.MsgRegisterContractResponse + 11, // [11:20] is the sub-list for method output_type + 2, // [2:11] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name 2, // [2:2] is the sub-list for extension extendee 0, // [0:2] is the sub-list for field type_name @@ -7847,6 +8849,30 @@ func file_fairyring_pep_tx_proto_init() { return nil } } + file_fairyring_pep_tx_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgRegisterContract); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fairyring_pep_tx_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgRegisterContractResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -7854,7 +8880,7 @@ func file_fairyring_pep_tx_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_fairyring_pep_tx_proto_rawDesc, NumEnums: 0, - NumMessages: 15, + NumMessages: 17, NumExtensions: 0, NumServices: 1, }, diff --git a/api/fairyring/pep/tx_grpc.pb.go b/api/fairyring/pep/tx_grpc.pb.go index 87acd533..3e91ea1e 100644 --- a/api/fairyring/pep/tx_grpc.pb.go +++ b/api/fairyring/pep/tx_grpc.pb.go @@ -27,6 +27,7 @@ const ( Msg_GetGeneralKeyshare_FullMethodName = "/fairyring.pep.Msg/GetGeneralKeyshare" Msg_RequestPrivateIdentity_FullMethodName = "/fairyring.pep.Msg/RequestPrivateIdentity" Msg_GetPrivateKeyshares_FullMethodName = "/fairyring.pep.Msg/GetPrivateKeyshares" + Msg_RegisterContract_FullMethodName = "/fairyring.pep.Msg/RegisterContract" ) // MsgClient is the client API for Msg service. @@ -44,6 +45,7 @@ type MsgClient interface { GetGeneralKeyshare(ctx context.Context, in *MsgGetGeneralKeyshare, opts ...grpc.CallOption) (*MsgGetGeneralKeyshareResponse, error) RequestPrivateIdentity(ctx context.Context, in *MsgRequestPrivateIdentity, opts ...grpc.CallOption) (*MsgRequestPrivateIdentityResponse, error) GetPrivateKeyshares(ctx context.Context, in *MsgGetPrivateKeyshares, opts ...grpc.CallOption) (*MsgGetPrivateKeysharesResponse, error) + RegisterContract(ctx context.Context, in *MsgRegisterContract, opts ...grpc.CallOption) (*MsgRegisterContractResponse, error) } type msgClient struct { @@ -126,6 +128,15 @@ func (c *msgClient) GetPrivateKeyshares(ctx context.Context, in *MsgGetPrivateKe return out, nil } +func (c *msgClient) RegisterContract(ctx context.Context, in *MsgRegisterContract, opts ...grpc.CallOption) (*MsgRegisterContractResponse, error) { + out := new(MsgRegisterContractResponse) + err := c.cc.Invoke(ctx, Msg_RegisterContract_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. // All implementations must embed UnimplementedMsgServer // for forward compatibility @@ -141,6 +152,7 @@ type MsgServer interface { GetGeneralKeyshare(context.Context, *MsgGetGeneralKeyshare) (*MsgGetGeneralKeyshareResponse, error) RequestPrivateIdentity(context.Context, *MsgRequestPrivateIdentity) (*MsgRequestPrivateIdentityResponse, error) GetPrivateKeyshares(context.Context, *MsgGetPrivateKeyshares) (*MsgGetPrivateKeysharesResponse, error) + RegisterContract(context.Context, *MsgRegisterContract) (*MsgRegisterContractResponse, error) mustEmbedUnimplementedMsgServer() } @@ -172,6 +184,9 @@ func (UnimplementedMsgServer) RequestPrivateIdentity(context.Context, *MsgReques func (UnimplementedMsgServer) GetPrivateKeyshares(context.Context, *MsgGetPrivateKeyshares) (*MsgGetPrivateKeysharesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetPrivateKeyshares not implemented") } +func (UnimplementedMsgServer) RegisterContract(context.Context, *MsgRegisterContract) (*MsgRegisterContractResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterContract not implemented") +} func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {} // UnsafeMsgServer may be embedded to opt out of forward compatibility for this service. @@ -329,6 +344,24 @@ func _Msg_GetPrivateKeyshares_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Msg_RegisterContract_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRegisterContract) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RegisterContract(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Msg_RegisterContract_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RegisterContract(ctx, req.(*MsgRegisterContract)) + } + return interceptor(ctx, in, info, handler) +} + // Msg_ServiceDesc is the grpc.ServiceDesc for Msg service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -368,6 +401,10 @@ var Msg_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetPrivateKeyshares", Handler: _Msg_GetPrivateKeyshares_Handler, }, + { + MethodName: "RegisterContract", + Handler: _Msg_RegisterContract_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "fairyring/pep/tx.proto", diff --git a/app/ibc.go b/app/ibc.go index d5222069..b1276e8b 100644 --- a/app/ibc.go +++ b/app/ibc.go @@ -170,6 +170,20 @@ func (app *App) registerIBCModules(appOpts servertypes.AppOptions) error { AddRoute(icacontrollertypes.SubModuleName, icaControllerIBCModule). AddRoute(icahosttypes.SubModuleName, icaHostIBCModule) + acceptList := map[string]proto.Message{ + "/fairyring.keyshare.Query/VerifiableRandomness": &keysharemoduletypes.QueryVerifiableRandomnessResponse{}, + } + + // Add wasmd to IBC Router + wasmStack, err := app.registerWasmModules(appOpts, wasmkeeper.WithQueryPlugins( + &wasmkeeper.QueryPlugins{ + Grpc: wasmkeeper.AcceptListGrpcQuerier(acceptList, app.GRPCQueryRouter(), app.appCodec), + })) + if err != nil { + return err + } + ibcRouter.AddRoute(wasmtypes.ModuleName, wasmStack) + pepStack, err := app.registerPepModule() if err != nil { return err @@ -186,19 +200,6 @@ func (app *App) registerIBCModules(appOpts servertypes.AppOptions) error { govIBCModule := ibcfee.NewIBCMiddleware(gov.NewIBCModule(app.GovKeeper), app.IBCFeeKeeper) ibcRouter.AddRoute(govtypes.ModuleName, govIBCModule) - acceptList := map[string]proto.Message{ - "/fairyring.keyshare.Query/VerifiableRandomness": &keysharemoduletypes.QueryVerifiableRandomnessResponse{}, - } - - // Add wasmd to IBC Router - wasmStack, err := app.registerWasmModules(appOpts, wasmkeeper.WithQueryPlugins( - &wasmkeeper.QueryPlugins{ - Grpc: wasmkeeper.AcceptListGrpcQuerier(acceptList, app.GRPCQueryRouter(), app.appCodec), - })) - if err != nil { - return err - } - ibcRouter.AddRoute(wasmtypes.ModuleName, wasmStack) // this line is used by starport scaffolding # ibc/app/module app.IBCKeeper.SetRouter(ibcRouter) diff --git a/app/pep.go b/app/pep.go index 591569d5..45cfbe4c 100644 --- a/app/pep.go +++ b/app/pep.go @@ -21,6 +21,7 @@ func (app *App) registerPepModule() (porttypes.IBCModule, error) { } scopedPepKeeper := app.CapabilityKeeper.ScopeToModule(peptypes.ModuleName) + contractKeeper := app.WasmKeeper.NewDefaultPermissionKeeper(&app.WasmKeeper) // The last arguments can contain custom message handlers, and custom query handlers, // if we want to allow any custom callbacks @@ -34,6 +35,7 @@ func (app *App) registerPepModule() (porttypes.IBCModule, error) { scopedPepKeeper, app.AccountKeeper, app.BankKeeper, + contractKeeper, ) // register IBC modules diff --git a/go.mod b/go.mod index 67819d40..30363b1d 100644 --- a/go.mod +++ b/go.mod @@ -61,6 +61,8 @@ require ( google.golang.org/protobuf v1.34.1 ) +require github.com/regen-network/cosmos-proto v0.3.1 // indirect + require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 // indirect cloud.google.com/go v0.112.0 // indirect diff --git a/go.sum b/go.sum index 94de3d02..9ac3f2b8 100644 --- a/go.sum +++ b/go.sum @@ -1011,6 +1011,8 @@ github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43Z github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= +github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= diff --git a/proto/fairyring/pep/request_id.proto b/proto/fairyring/pep/request_id.proto index 9ffd4542..c5446fb5 100644 --- a/proto/fairyring/pep/request_id.proto +++ b/proto/fairyring/pep/request_id.proto @@ -17,3 +17,19 @@ message PrivateRequest { string pubkey = 3; repeated fairyring.common.EncryptedKeyshare encrypted_keyshares = 5; } + +message ContractDetails { + string registrar = 1; + string contract_address = 2; +} + +message RegisterdContract { + string identity = 1; + repeated ContractDetails contracts = 2; +} + +message ExecuteContractMsg { + string identity = 1; + string pubkey = 2; + string aggr_keyshare = 3; +} diff --git a/proto/fairyring/pep/tx.proto b/proto/fairyring/pep/tx.proto index 2edb8ae6..979e48fd 100644 --- a/proto/fairyring/pep/tx.proto +++ b/proto/fairyring/pep/tx.proto @@ -31,6 +31,7 @@ service Msg { rpc GetGeneralKeyshare (MsgGetGeneralKeyshare ) returns (MsgGetGeneralKeyshareResponse ); rpc RequestPrivateIdentity (MsgRequestPrivateIdentity ) returns (MsgRequestPrivateIdentityResponse ); rpc GetPrivateKeyshares (MsgGetPrivateKeyshares ) returns (MsgGetPrivateKeysharesResponse ); + rpc RegisterContract (MsgRegisterContract ) returns (MsgRegisterContractResponse ); } // MsgUpdateParams is the Msg/UpdateParams request type. message MsgUpdateParams { @@ -114,3 +115,11 @@ message MsgGetPrivateKeyshares { message MsgGetPrivateKeysharesResponse {} +message MsgRegisterContract { + option (cosmos.msg.v1.signer) = "creator"; + string creator = 1; + string contract_address = 2; + string identity = 3; +} + +message MsgRegisterContractResponse {} \ No newline at end of file diff --git a/x/pep/keeper/contract.go b/x/pep/keeper/contract.go new file mode 100644 index 00000000..646f944c --- /dev/null +++ b/x/pep/keeper/contract.go @@ -0,0 +1,100 @@ +package keeper + +import ( + "context" + + "cosmossdk.io/store/prefix" + storetypes "cosmossdk.io/store/types" + "github.com/Fairblock/fairyring/x/pep/types" + "github.com/cosmos/cosmos-sdk/runtime" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SetContractEntry set a specific contract entry in the store by identity +func (k Keeper) SetContractEntry(ctx context.Context, contract types.RegisterdContract) { + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.ContractKeyPrefix)) + b := k.cdc.MustMarshal(&contract) + store.Set([]byte(contract.Identity), b) +} + +// GetContractEntriesByID returns a the list of contracts for an identity +func (k Keeper) GetContractEntriesByID( + ctx context.Context, + identity string, +) (val types.RegisterdContract, found bool) { + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.ContractKeyPrefix)) + + b := store.Get([]byte(identity)) + if b == nil { + return val, false + } + + k.cdc.MustUnmarshal(b, &val) + return val, true +} + +// GetContractEntry fetches the details of a contract by identity and contract address +func (k Keeper) GetContractEntry( + ctx context.Context, + reqID string, + contractAddr string, +) (val types.ContractDetails, found bool) { + c, found := k.GetContractEntriesByID(ctx, reqID) + if !found || len(c.Contracts) == 0 { + return types.ContractDetails{}, found + } + + for _, con := range c.Contracts { + if con.ContractAddress == contractAddr { + return *con, true + } + } + + return types.ContractDetails{}, false +} + +// AppendContractToEntry appends a new contract detail to an already existing contract entry +func (k Keeper) AppendContractToEntry( + ctx context.Context, + contract types.RegisterdContract, +) { + c, found := k.GetContractEntriesByID(ctx, contract.Identity) + if !found { + k.logger.Error("contract entry not found for identity: ", contract.Identity) + return + } + c.Contracts = append(c.Contracts, contract.Contracts...) + k.SetContractEntry(ctx, c) +} + +// GetAllContractEntries returns all contracts for all identities +func (k Keeper) GetAllContractEntries(ctx context.Context) (list []types.RegisterdContract) { + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.ContractKeyPrefix)) + iterator := storetypes.KVStorePrefixIterator(store, []byte{}) + + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var val types.RegisterdContract + k.cdc.MustUnmarshal(iterator.Value(), &val) + list = append(list, val) + } + + return +} + +func (k Keeper) ExecuteContract(ctx sdk.Context, contractAddr string, msg types.ExecuteContractMsg) { + addr := sdk.MustAccAddressFromBech32(contractAddr) + msgBytes, err := msg.Marshal() + if err != nil { + k.logger.Error("error marshalling msg for contract: %s", contractAddr) + return + } + _, err = k.wasmKeeper.Execute(ctx, addr, addr, msgBytes, sdk.Coins{}) + if err != nil { + k.logger.Error("error executing contract: %s", contractAddr) + } +} diff --git a/x/pep/keeper/keeper.go b/x/pep/keeper/keeper.go index 8a4a569c..701aa87c 100644 --- a/x/pep/keeper/keeper.go +++ b/x/pep/keeper/keeper.go @@ -36,6 +36,7 @@ type ( accountKeeper types.AccountKeeper bankKeeper types.BankKeeper + wasmKeeper types.WasmKeeper } ) @@ -50,6 +51,7 @@ func NewKeeper( accountKeeper types.AccountKeeper, bankKeeper types.BankKeeper, + wasmKeeper types.WasmKeeper, ) Keeper { if _, err := sdk.AccAddressFromBech32(authority); err != nil { panic(fmt.Sprintf("invalid authority address: %s", authority)) @@ -65,6 +67,7 @@ func NewKeeper( scopedKeeper: scopedKeeper, accountKeeper: accountKeeper, bankKeeper: bankKeeper, + wasmKeeper: wasmKeeper, } } @@ -156,3 +159,7 @@ func (k Keeper) SetRequestCount(ctx sdk.Context, requestNumber uint64) { store := prefix.NewStore(storeAdapter, []byte{}) store.Set(types.RequestsCountKey, []byte(strconv.FormatUint(requestNumber, 10))) } + +func (k Keeper) SetWasmKeeper(wk types.WasmKeeper) { + k.wasmKeeper = wk +} diff --git a/x/pep/keeper/msg_register_contract.go b/x/pep/keeper/msg_register_contract.go new file mode 100644 index 00000000..36ffcd70 --- /dev/null +++ b/x/pep/keeper/msg_register_contract.go @@ -0,0 +1,42 @@ +package keeper + +import ( + "context" + "errors" + + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (k msgServer) RegisterContract( + goCtx context.Context, + msg *types.MsgRegisterContract, +) (*types.MsgRegisterContractResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + var contDetails = types.ContractDetails{ + Registrar: msg.Creator, + ContractAddress: msg.ContractAddress, + } + + entry, found := k.GetContractEntriesByID(ctx, msg.Identity) + if found { + if len(entry.Contracts) != 0 { + for _, c := range entry.Contracts { + if c.ContractAddress == msg.ContractAddress { + return nil, errors.New("contract is already registered for this identity") + } + } + } else { + entry.Contracts = make([]*types.ContractDetails, 0) + } + + } + + entry.Identity = msg.Identity + entry.Contracts = append(entry.Contracts, &contDetails) + + k.SetContractEntry(ctx, entry) + + return &types.MsgRegisterContractResponse{}, nil +} diff --git a/x/pep/module/module.go b/x/pep/module/module.go index 7282a2dc..f79c2499 100644 --- a/x/pep/module/module.go +++ b/x/pep/module/module.go @@ -277,6 +277,23 @@ func (am AppModule) BeginBlock(cctx context.Context) error { continue } + contracts, found := am.keeper.GetContractEntriesByID(ctx, entry.Identity) + if found { + if len(contracts.Contracts) != 0 { + for _, contract := range contracts.Contracts { + am.keeper.ExecuteContract( + ctx, + contract.ContractAddress, + types.ExecuteContractMsg{ + Identity: entry.Identity, + Pubkey: entry.Pubkey, + AggrKeyshare: entry.AggrKeyshare, + }, + ) + } + } + } + if entry.TxList == nil { am.keeper.Logger().Info("No encrypted txs found for entry with req-id: ", entry.RequestId) am.keeper.RemoveExecutionQueueEntry(ctx, entry.Identity) diff --git a/x/pep/types/expected_keepers.go b/x/pep/types/expected_keepers.go index 854dfc9f..9de8b4da 100644 --- a/x/pep/types/expected_keepers.go +++ b/x/pep/types/expected_keepers.go @@ -27,3 +27,8 @@ type ParamSubspace interface { Get(context.Context, []byte, interface{}) Set(context.Context, []byte, interface{}) } + +// WasmKeeper defines the expected interface for the wasm module. +type WasmKeeper interface { + Execute(ctx sdk.Context, contractAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) ([]byte, error) +} diff --git a/x/pep/types/key_request_id.go b/x/pep/types/key_request_id.go index 1aa0f903..83a5031a 100644 --- a/x/pep/types/key_request_id.go +++ b/x/pep/types/key_request_id.go @@ -11,6 +11,7 @@ const ( // RequestIdKeyPrefix is the prefix to retrieve all RequestId RequestIdKeyPrefix = "RequestId/value/" PrivateRequestIdKeyPrefix = "PrivateRequestId/value/" + ContractKeyPrefix = "Contract/value/" ) // RequestIdKey returns the store key to retrieve a RequestId from the index fields diff --git a/x/pep/types/request_id.pb.go b/x/pep/types/request_id.pb.go index 280ee896..8d35b714 100644 --- a/x/pep/types/request_id.pb.go +++ b/x/pep/types/request_id.pb.go @@ -144,34 +144,209 @@ func (m *PrivateRequest) GetEncryptedKeyshares() []*types.EncryptedKeyshare { return nil } +type ContractDetails struct { + Registrar string `protobuf:"bytes,1,opt,name=registrar,proto3" json:"registrar,omitempty"` + ContractAddress string `protobuf:"bytes,2,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"` +} + +func (m *ContractDetails) Reset() { *m = ContractDetails{} } +func (m *ContractDetails) String() string { return proto.CompactTextString(m) } +func (*ContractDetails) ProtoMessage() {} +func (*ContractDetails) Descriptor() ([]byte, []int) { + return fileDescriptor_3e457d2e8ff0411e, []int{2} +} +func (m *ContractDetails) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ContractDetails) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ContractDetails.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 *ContractDetails) XXX_Merge(src proto.Message) { + xxx_messageInfo_ContractDetails.Merge(m, src) +} +func (m *ContractDetails) XXX_Size() int { + return m.Size() +} +func (m *ContractDetails) XXX_DiscardUnknown() { + xxx_messageInfo_ContractDetails.DiscardUnknown(m) +} + +var xxx_messageInfo_ContractDetails proto.InternalMessageInfo + +func (m *ContractDetails) GetRegistrar() string { + if m != nil { + return m.Registrar + } + return "" +} + +func (m *ContractDetails) GetContractAddress() string { + if m != nil { + return m.ContractAddress + } + return "" +} + +type RegisterdContract struct { + Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + Contracts []*ContractDetails `protobuf:"bytes,2,rep,name=contracts,proto3" json:"contracts,omitempty"` +} + +func (m *RegisterdContract) Reset() { *m = RegisterdContract{} } +func (m *RegisterdContract) String() string { return proto.CompactTextString(m) } +func (*RegisterdContract) ProtoMessage() {} +func (*RegisterdContract) Descriptor() ([]byte, []int) { + return fileDescriptor_3e457d2e8ff0411e, []int{3} +} +func (m *RegisterdContract) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RegisterdContract) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RegisterdContract.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 *RegisterdContract) XXX_Merge(src proto.Message) { + xxx_messageInfo_RegisterdContract.Merge(m, src) +} +func (m *RegisterdContract) XXX_Size() int { + return m.Size() +} +func (m *RegisterdContract) XXX_DiscardUnknown() { + xxx_messageInfo_RegisterdContract.DiscardUnknown(m) +} + +var xxx_messageInfo_RegisterdContract proto.InternalMessageInfo + +func (m *RegisterdContract) GetIdentity() string { + if m != nil { + return m.Identity + } + return "" +} + +func (m *RegisterdContract) GetContracts() []*ContractDetails { + if m != nil { + return m.Contracts + } + return nil +} + +type ExecuteContractMsg struct { + Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + Pubkey string `protobuf:"bytes,2,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + AggrKeyshare string `protobuf:"bytes,3,opt,name=aggr_keyshare,json=aggrKeyshare,proto3" json:"aggr_keyshare,omitempty"` +} + +func (m *ExecuteContractMsg) Reset() { *m = ExecuteContractMsg{} } +func (m *ExecuteContractMsg) String() string { return proto.CompactTextString(m) } +func (*ExecuteContractMsg) ProtoMessage() {} +func (*ExecuteContractMsg) Descriptor() ([]byte, []int) { + return fileDescriptor_3e457d2e8ff0411e, []int{4} +} +func (m *ExecuteContractMsg) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExecuteContractMsg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExecuteContractMsg.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 *ExecuteContractMsg) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExecuteContractMsg.Merge(m, src) +} +func (m *ExecuteContractMsg) XXX_Size() int { + return m.Size() +} +func (m *ExecuteContractMsg) XXX_DiscardUnknown() { + xxx_messageInfo_ExecuteContractMsg.DiscardUnknown(m) +} + +var xxx_messageInfo_ExecuteContractMsg proto.InternalMessageInfo + +func (m *ExecuteContractMsg) GetIdentity() string { + if m != nil { + return m.Identity + } + return "" +} + +func (m *ExecuteContractMsg) GetPubkey() string { + if m != nil { + return m.Pubkey + } + return "" +} + +func (m *ExecuteContractMsg) GetAggrKeyshare() string { + if m != nil { + return m.AggrKeyshare + } + return "" +} + func init() { proto.RegisterType((*RequestId)(nil), "fairyring.pep.RequestId") proto.RegisterType((*PrivateRequest)(nil), "fairyring.pep.PrivateRequest") + proto.RegisterType((*ContractDetails)(nil), "fairyring.pep.ContractDetails") + proto.RegisterType((*RegisterdContract)(nil), "fairyring.pep.RegisterdContract") + proto.RegisterType((*ExecuteContractMsg)(nil), "fairyring.pep.ExecuteContractMsg") } func init() { proto.RegisterFile("fairyring/pep/request_id.proto", fileDescriptor_3e457d2e8ff0411e) } var fileDescriptor_3e457d2e8ff0411e = []byte{ - // 294 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0x3d, 0x4e, 0xc3, 0x30, - 0x18, 0x86, 0x6b, 0xaa, 0x16, 0xd5, 0x08, 0x06, 0x53, 0x50, 0xd4, 0xc1, 0xaa, 0xda, 0xa5, 0x62, - 0x88, 0x25, 0x18, 0xd9, 0x10, 0x20, 0x55, 0x2c, 0xa8, 0x62, 0x62, 0x89, 0xf2, 0xf3, 0x91, 0x5a, - 0xa5, 0xb1, 0xf3, 0xc5, 0x41, 0xe4, 0x16, 0xdc, 0x84, 0x6b, 0x30, 0x76, 0x64, 0x44, 0xc9, 0x45, - 0x50, 0x9d, 0x94, 0x08, 0x06, 0x36, 0xbf, 0x3f, 0x7a, 0x64, 0xbf, 0xa6, 0xfc, 0xc9, 0x97, 0x58, - 0xa0, 0x4c, 0x62, 0xa1, 0x41, 0x0b, 0x84, 0x34, 0x87, 0xcc, 0x78, 0x32, 0x72, 0x35, 0x2a, 0xa3, - 0xd8, 0xe1, 0x4f, 0xee, 0x6a, 0xd0, 0xa3, 0x61, 0xac, 0x62, 0x65, 0x13, 0xb1, 0x3d, 0xd5, 0xa5, - 0xd1, 0xb4, 0x85, 0x84, 0x6a, 0xbd, 0x56, 0x89, 0xc8, 0x96, 0x3e, 0x42, 0xe4, 0x99, 0x42, 0x43, - 0x56, 0x97, 0x26, 0x97, 0x74, 0xb0, 0xa8, 0xe9, 0xf3, 0x88, 0x39, 0x74, 0x3f, 0x44, 0xf0, 0x8d, - 0x42, 0x87, 0x8c, 0xc9, 0x6c, 0xb0, 0xd8, 0x49, 0x36, 0xa4, 0x3d, 0x84, 0x74, 0x1e, 0x39, 0x7b, - 0xd6, 0xaf, 0xc5, 0xe4, 0x9d, 0xd0, 0xa3, 0x7b, 0x94, 0x2f, 0xbe, 0x81, 0x06, 0xf2, 0x0f, 0xe2, - 0x84, 0xf6, 0x11, 0x52, 0x4f, 0xfe, 0x66, 0xb0, 0x53, 0xda, 0xd7, 0x79, 0xb0, 0x82, 0xc2, 0xe9, - 0x5a, 0xbb, 0x51, 0xec, 0x81, 0x1e, 0x43, 0x12, 0x62, 0xa1, 0x0d, 0x44, 0xde, 0x0a, 0x0a, 0x7b, - 0xf7, 0xcc, 0xe9, 0x8d, 0xbb, 0xb3, 0x83, 0xf3, 0xa9, 0xdb, 0x0e, 0x50, 0xbf, 0xcd, 0xbd, 0xd9, - 0x95, 0xef, 0x9a, 0xee, 0x82, 0xc1, 0x5f, 0x2b, 0xbb, 0xba, 0xfe, 0x28, 0x39, 0xd9, 0x94, 0x9c, - 0x7c, 0x95, 0x9c, 0xbc, 0x55, 0xbc, 0xb3, 0xa9, 0x78, 0xe7, 0xb3, 0xe2, 0x9d, 0xc7, 0xb3, 0x58, - 0x9a, 0x65, 0x1e, 0x6c, 0x71, 0xe2, 0xd6, 0x97, 0x18, 0x3c, 0xab, 0x70, 0x25, 0xda, 0x09, 0x5f, - 0xed, 0x4f, 0xd8, 0xe9, 0x82, 0xbe, 0xdd, 0xee, 0xe2, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x14, 0x1c, - 0xef, 0xb3, 0xa7, 0x01, 0x00, 0x00, + // 422 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x8d, 0x5b, 0x35, 0x90, 0x81, 0x52, 0x58, 0x0a, 0xb2, 0x22, 0x64, 0x55, 0xce, 0xa5, 0x70, + 0xb0, 0x25, 0x38, 0xc2, 0x05, 0x68, 0x91, 0x2a, 0x84, 0x84, 0x2c, 0x4e, 0xbd, 0x58, 0x1b, 0xef, + 0xe0, 0xae, 0xd2, 0x78, 0x37, 0xb3, 0x1b, 0x54, 0xff, 0x05, 0x7f, 0xc2, 0x6f, 0x70, 0xec, 0x91, + 0x23, 0x4a, 0x7e, 0xa4, 0xf2, 0xda, 0x1b, 0x2b, 0x3d, 0xe4, 0xb6, 0xf3, 0xf6, 0xcd, 0xdb, 0xd9, + 0x37, 0x0f, 0xa2, 0x9f, 0x5c, 0x52, 0x4d, 0xb2, 0x2a, 0x53, 0x8d, 0x3a, 0x25, 0x5c, 0x2c, 0xd1, + 0xd8, 0x5c, 0x8a, 0x44, 0x93, 0xb2, 0x8a, 0x1d, 0x6e, 0xee, 0x13, 0x8d, 0x7a, 0x7c, 0x5c, 0xaa, + 0x52, 0xb9, 0x9b, 0xb4, 0x39, 0xb5, 0xa4, 0xf1, 0xa4, 0x17, 0x29, 0xd4, 0x7c, 0xae, 0xaa, 0xd4, + 0x5c, 0x71, 0x42, 0x91, 0xdb, 0x5a, 0xa3, 0x69, 0x49, 0xf1, 0x7b, 0x18, 0x65, 0xad, 0xfa, 0x85, + 0x60, 0x21, 0x3c, 0x28, 0x08, 0xb9, 0x55, 0x14, 0x06, 0x27, 0xc1, 0xe9, 0x28, 0xf3, 0x25, 0x3b, + 0x86, 0x03, 0xc2, 0xc5, 0x85, 0x08, 0xf7, 0x1c, 0xde, 0x16, 0xf1, 0x9f, 0x00, 0x9e, 0x7c, 0x27, + 0xf9, 0x8b, 0x5b, 0xec, 0x44, 0x76, 0x48, 0xbc, 0x80, 0x21, 0xe1, 0x22, 0x97, 0xdb, 0x1a, 0xec, + 0x25, 0x0c, 0xf5, 0x72, 0x3a, 0xc3, 0x3a, 0xdc, 0x77, 0x70, 0x57, 0xb1, 0x1f, 0xf0, 0x1c, 0xab, + 0x82, 0x6a, 0x6d, 0x51, 0xe4, 0x33, 0xac, 0xdd, 0xec, 0x26, 0x3c, 0x38, 0xd9, 0x3f, 0x7d, 0xf4, + 0x76, 0x92, 0xf4, 0x06, 0xb4, 0x7f, 0x4b, 0xce, 0x3d, 0xf9, 0x6b, 0xc7, 0xcd, 0x18, 0xde, 0x87, + 0x4c, 0x7c, 0x09, 0x47, 0x9f, 0x55, 0x65, 0x89, 0x17, 0xf6, 0x0c, 0x2d, 0x97, 0xd7, 0x86, 0xbd, + 0x82, 0x11, 0x61, 0x29, 0x8d, 0x25, 0xee, 0x67, 0xee, 0x01, 0xf6, 0x1a, 0x9e, 0x16, 0x5d, 0x43, + 0xce, 0x85, 0x20, 0x34, 0xa6, 0x9b, 0xff, 0xc8, 0xe3, 0x1f, 0x5b, 0x38, 0x9e, 0xc3, 0xb3, 0xcc, + 0xf5, 0x21, 0x09, 0xff, 0x08, 0x1b, 0xc3, 0x43, 0x29, 0xb0, 0xb2, 0xd2, 0xd6, 0x9d, 0xf8, 0xa6, + 0x66, 0x1f, 0x60, 0xe4, 0x35, 0x1a, 0xd1, 0xe6, 0x63, 0x51, 0xb2, 0xb5, 0xd9, 0xe4, 0xde, 0xb0, + 0x59, 0xdf, 0x10, 0xcf, 0x81, 0x9d, 0xdf, 0x60, 0xb1, 0xb4, 0xe8, 0x49, 0xdf, 0x4c, 0xb9, 0xf3, + 0xbd, 0xde, 0xea, 0xbd, 0x2d, 0xab, 0x27, 0x70, 0xc8, 0xcb, 0x92, 0x36, 0x2e, 0x77, 0x9b, 0x78, + 0xdc, 0x80, 0xde, 0xba, 0x4f, 0x67, 0x7f, 0x57, 0x51, 0x70, 0xbb, 0x8a, 0x82, 0xff, 0xab, 0x28, + 0xf8, 0xbd, 0x8e, 0x06, 0xb7, 0xeb, 0x68, 0xf0, 0x6f, 0x1d, 0x0d, 0x2e, 0xdf, 0x94, 0xd2, 0x5e, + 0x2d, 0xa7, 0xcd, 0x22, 0xd2, 0x2f, 0x5c, 0xd2, 0xf4, 0x5a, 0x15, 0xb3, 0xb4, 0x0f, 0xdf, 0x8d, + 0xcb, 0xb0, 0x0b, 0xdd, 0x74, 0xe8, 0x52, 0xf7, 0xee, 0x2e, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x6f, + 0x5f, 0xf7, 0xe1, 0x02, 0x00, 0x00, } func (m *RequestId) Marshal() (dAtA []byte, err error) { @@ -269,6 +444,131 @@ func (m *PrivateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ContractDetails) 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 *ContractDetails) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ContractDetails) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ContractAddress) > 0 { + i -= len(m.ContractAddress) + copy(dAtA[i:], m.ContractAddress) + i = encodeVarintRequestId(dAtA, i, uint64(len(m.ContractAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.Registrar) > 0 { + i -= len(m.Registrar) + copy(dAtA[i:], m.Registrar) + i = encodeVarintRequestId(dAtA, i, uint64(len(m.Registrar))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RegisterdContract) 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 *RegisterdContract) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RegisterdContract) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Contracts) > 0 { + for iNdEx := len(m.Contracts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Contracts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintRequestId(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Identity) > 0 { + i -= len(m.Identity) + copy(dAtA[i:], m.Identity) + i = encodeVarintRequestId(dAtA, i, uint64(len(m.Identity))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ExecuteContractMsg) 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 *ExecuteContractMsg) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExecuteContractMsg) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AggrKeyshare) > 0 { + i -= len(m.AggrKeyshare) + copy(dAtA[i:], m.AggrKeyshare) + i = encodeVarintRequestId(dAtA, i, uint64(len(m.AggrKeyshare))) + i-- + dAtA[i] = 0x1a + } + if len(m.Pubkey) > 0 { + i -= len(m.Pubkey) + copy(dAtA[i:], m.Pubkey) + i = encodeVarintRequestId(dAtA, i, uint64(len(m.Pubkey))) + i-- + dAtA[i] = 0x12 + } + if len(m.Identity) > 0 { + i -= len(m.Identity) + copy(dAtA[i:], m.Identity) + i = encodeVarintRequestId(dAtA, i, uint64(len(m.Identity))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintRequestId(dAtA []byte, offset int, v uint64) int { offset -= sovRequestId(v) base := offset @@ -324,6 +624,63 @@ func (m *PrivateRequest) Size() (n int) { return n } +func (m *ContractDetails) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Registrar) + if l > 0 { + n += 1 + l + sovRequestId(uint64(l)) + } + l = len(m.ContractAddress) + if l > 0 { + n += 1 + l + sovRequestId(uint64(l)) + } + return n +} + +func (m *RegisterdContract) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Identity) + if l > 0 { + n += 1 + l + sovRequestId(uint64(l)) + } + if len(m.Contracts) > 0 { + for _, e := range m.Contracts { + l = e.Size() + n += 1 + l + sovRequestId(uint64(l)) + } + } + return n +} + +func (m *ExecuteContractMsg) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Identity) + if l > 0 { + n += 1 + l + sovRequestId(uint64(l)) + } + l = len(m.Pubkey) + if l > 0 { + n += 1 + l + sovRequestId(uint64(l)) + } + l = len(m.AggrKeyshare) + if l > 0 { + n += 1 + l + sovRequestId(uint64(l)) + } + return n +} + func sovRequestId(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -624,6 +981,382 @@ func (m *PrivateRequest) Unmarshal(dAtA []byte) error { } return nil } +func (m *ContractDetails) 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 ErrIntOverflowRequestId + } + 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: ContractDetails: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ContractDetails: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Registrar", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestId + } + 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 ErrInvalidLengthRequestId + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRequestId + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Registrar = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestId + } + 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 ErrInvalidLengthRequestId + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRequestId + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ContractAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRequestId(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthRequestId + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RegisterdContract) 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 ErrIntOverflowRequestId + } + 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: RegisterdContract: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RegisterdContract: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Identity", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestId + } + 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 ErrInvalidLengthRequestId + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRequestId + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Identity = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Contracts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestId + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRequestId + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRequestId + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Contracts = append(m.Contracts, &ContractDetails{}) + if err := m.Contracts[len(m.Contracts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRequestId(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthRequestId + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExecuteContractMsg) 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 ErrIntOverflowRequestId + } + 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: ExecuteContractMsg: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExecuteContractMsg: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Identity", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestId + } + 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 ErrInvalidLengthRequestId + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRequestId + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Identity = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pubkey", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestId + } + 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 ErrInvalidLengthRequestId + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRequestId + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pubkey = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggrKeyshare", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRequestId + } + 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 ErrInvalidLengthRequestId + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRequestId + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AggrKeyshare = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRequestId(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthRequestId + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipRequestId(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/pep/types/tx.pb.go b/x/pep/types/tx.pb.go index 6a463fe8..be95dc58 100644 --- a/x/pep/types/tx.pb.go +++ b/x/pep/types/tx.pb.go @@ -766,6 +766,102 @@ func (m *MsgGetPrivateKeysharesResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgGetPrivateKeysharesResponse proto.InternalMessageInfo +type MsgRegisterContract struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + ContractAddress string `protobuf:"bytes,2,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"` + Identity string `protobuf:"bytes,3,opt,name=identity,proto3" json:"identity,omitempty"` +} + +func (m *MsgRegisterContract) Reset() { *m = MsgRegisterContract{} } +func (m *MsgRegisterContract) String() string { return proto.CompactTextString(m) } +func (*MsgRegisterContract) ProtoMessage() {} +func (*MsgRegisterContract) Descriptor() ([]byte, []int) { + return fileDescriptor_f6953e463911e1ec, []int{15} +} +func (m *MsgRegisterContract) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRegisterContract) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRegisterContract.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 *MsgRegisterContract) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRegisterContract.Merge(m, src) +} +func (m *MsgRegisterContract) XXX_Size() int { + return m.Size() +} +func (m *MsgRegisterContract) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRegisterContract.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRegisterContract proto.InternalMessageInfo + +func (m *MsgRegisterContract) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *MsgRegisterContract) GetContractAddress() string { + if m != nil { + return m.ContractAddress + } + return "" +} + +func (m *MsgRegisterContract) GetIdentity() string { + if m != nil { + return m.Identity + } + return "" +} + +type MsgRegisterContractResponse struct { +} + +func (m *MsgRegisterContractResponse) Reset() { *m = MsgRegisterContractResponse{} } +func (m *MsgRegisterContractResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRegisterContractResponse) ProtoMessage() {} +func (*MsgRegisterContractResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f6953e463911e1ec, []int{16} +} +func (m *MsgRegisterContractResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRegisterContractResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRegisterContractResponse.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 *MsgRegisterContractResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRegisterContractResponse.Merge(m, src) +} +func (m *MsgRegisterContractResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRegisterContractResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRegisterContractResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRegisterContractResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgUpdateParams)(nil), "fairyring.pep.MsgUpdateParams") proto.RegisterType((*MsgUpdateParamsResponse)(nil), "fairyring.pep.MsgUpdateParamsResponse") @@ -782,65 +878,72 @@ func init() { proto.RegisterType((*MsgRequestPrivateIdentityResponse)(nil), "fairyring.pep.MsgRequestPrivateIdentityResponse") proto.RegisterType((*MsgGetPrivateKeyshares)(nil), "fairyring.pep.MsgGetPrivateKeyshares") proto.RegisterType((*MsgGetPrivateKeysharesResponse)(nil), "fairyring.pep.MsgGetPrivateKeysharesResponse") + proto.RegisterType((*MsgRegisterContract)(nil), "fairyring.pep.MsgRegisterContract") + proto.RegisterType((*MsgRegisterContractResponse)(nil), "fairyring.pep.MsgRegisterContractResponse") } func init() { proto.RegisterFile("fairyring/pep/tx.proto", fileDescriptor_f6953e463911e1ec) } var fileDescriptor_f6953e463911e1ec = []byte{ - // 848 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcf, 0x6f, 0x1b, 0x45, - 0x14, 0xce, 0x26, 0xa9, 0x91, 0x5f, 0x0b, 0x55, 0x96, 0x24, 0x75, 0x16, 0xd8, 0x04, 0x97, 0x22, - 0xcb, 0xb4, 0xbb, 0x24, 0x20, 0x84, 0x72, 0xab, 0x09, 0xa4, 0x55, 0x65, 0x29, 0xda, 0x40, 0x25, - 0xb8, 0x58, 0xb3, 0xde, 0xd7, 0xf1, 0xca, 0x3f, 0x66, 0x3d, 0x33, 0x0e, 0x59, 0x4e, 0x15, 0x47, - 0x4e, 0x1c, 0xf9, 0x03, 0x38, 0x70, 0xcc, 0x81, 0x3f, 0xa2, 0x07, 0x0e, 0x15, 0x27, 0x4e, 0x80, - 0x92, 0x43, 0xfe, 0x0c, 0xd0, 0xfe, 0x74, 0xbc, 0x3f, 0x5c, 0xa7, 0x17, 0x7b, 0x67, 0xde, 0x37, - 0xef, 0xfb, 0xbe, 0xb7, 0xf3, 0x9e, 0x16, 0x36, 0x9f, 0x11, 0x97, 0xfb, 0xdc, 0x1d, 0x51, 0xd3, - 0x43, 0xcf, 0x94, 0xa7, 0x86, 0xc7, 0x99, 0x64, 0xea, 0x9b, 0xe9, 0xbe, 0xe1, 0xa1, 0xa7, 0xad, - 0x91, 0xa1, 0x3b, 0x62, 0x66, 0xf8, 0x1b, 0x21, 0xb4, 0x3b, 0x5d, 0x26, 0x86, 0x4c, 0x98, 0x43, - 0x41, 0xcd, 0x93, 0xdd, 0xe0, 0x2f, 0x0e, 0x6c, 0x45, 0x81, 0x4e, 0xb8, 0x32, 0xa3, 0x45, 0x1c, - 0xd2, 0x29, 0x63, 0x74, 0x80, 0x66, 0xb8, 0xb2, 0x27, 0xcf, 0x4c, 0x67, 0xc2, 0x89, 0x74, 0xd9, - 0x28, 0x8e, 0xaf, 0x53, 0x46, 0x59, 0x74, 0x2e, 0x78, 0x8a, 0x77, 0xb5, 0x59, 0x8d, 0x1e, 0xe1, - 0x64, 0x98, 0x64, 0x6c, 0xcc, 0xc6, 0x08, 0xa5, 0x1c, 0x29, 0x91, 0xe8, 0x74, 0xfa, 0xe8, 0x77, - 0x44, 0x8f, 0x70, 0x4c, 0xb8, 0x63, 0xbd, 0x36, 0x11, 0x68, 0x9e, 0xec, 0xda, 0x28, 0xc9, 0xae, - 0xd9, 0x65, 0x6e, 0xcc, 0x5d, 0xff, 0x43, 0x81, 0xdb, 0x6d, 0x41, 0xbf, 0xf1, 0x1c, 0x22, 0xf1, - 0x28, 0xe4, 0x50, 0x3f, 0x83, 0x2a, 0x99, 0xc8, 0x1e, 0xe3, 0xae, 0xf4, 0x6b, 0xca, 0x8e, 0xd2, - 0xa8, 0xb6, 0x6a, 0x7f, 0xfe, 0xfe, 0x60, 0x3d, 0x36, 0xf5, 0xd0, 0x71, 0x38, 0x0a, 0x71, 0x2c, - 0x03, 0x7e, 0x6b, 0x0a, 0x55, 0x3f, 0x87, 0x4a, 0xa4, 0xb2, 0xb6, 0xbc, 0xa3, 0x34, 0x6e, 0xee, - 0x6d, 0x18, 0x33, 0xe5, 0x34, 0xa2, 0xf4, 0xad, 0xea, 0x8b, 0xbf, 0xb7, 0x97, 0x7e, 0xbb, 0x3c, - 0x6b, 0x2a, 0x56, 0x8c, 0xdf, 0x3f, 0xfc, 0xf1, 0xf2, 0xac, 0x39, 0xcd, 0xf4, 0xd3, 0xe5, 0x59, - 0xf3, 0x53, 0xea, 0xca, 0xde, 0xc4, 0x36, 0xba, 0x6c, 0x68, 0x7e, 0x45, 0x5c, 0x6e, 0x0f, 0x58, - 0xb7, 0x6f, 0x4e, 0x7d, 0x9f, 0x86, 0xce, 0x33, 0xd2, 0xeb, 0x5b, 0x70, 0x27, 0xb3, 0x65, 0xa1, - 0xf0, 0xd8, 0x48, 0x60, 0xfd, 0xb9, 0x02, 0xeb, 0x6d, 0x41, 0x8f, 0x27, 0xf6, 0xd0, 0x95, 0x5f, - 0x8e, 0xba, 0xdc, 0xf7, 0x24, 0x3a, 0x5f, 0x9f, 0xaa, 0x35, 0x78, 0xa3, 0xcb, 0x91, 0x48, 0xc6, - 0x23, 0xb3, 0x56, 0xb2, 0x54, 0x55, 0x58, 0x75, 0x88, 0x24, 0xa1, 0x9d, 0xaa, 0x15, 0x3e, 0xab, - 0xf7, 0x61, 0x4d, 0x12, 0x4e, 0x51, 0xb6, 0x02, 0x41, 0x8f, 0xd0, 0xa5, 0x3d, 0x59, 0x5b, 0xd9, - 0x51, 0x1a, 0xab, 0x56, 0x3e, 0xb0, 0x7f, 0x2b, 0x30, 0x96, 0xe4, 0xab, 0x7b, 0xf0, 0x4e, 0xaa, - 0xe0, 0x10, 0x47, 0xc8, 0xc9, 0xe0, 0xf5, 0x85, 0x6c, 0x40, 0x85, 0xe3, 0xb8, 0xe3, 0x3a, 0x21, - 0x7b, 0xd5, 0xba, 0xc1, 0x71, 0xfc, 0xd8, 0xc9, 0x30, 0xea, 0xf0, 0x6e, 0x91, 0xe7, 0xb4, 0x28, - 0xe3, 0x50, 0xd1, 0x17, 0x01, 0x1a, 0x1f, 0xa6, 0xb7, 0xe8, 0x09, 0xfa, 0xc7, 0xc1, 0x1d, 0x9a, - 0xa3, 0x68, 0x13, 0x2a, 0xbd, 0xc8, 0xfb, 0x72, 0xe8, 0x3d, 0x5e, 0xa5, 0x4a, 0x57, 0xa6, 0x4a, - 0x33, 0x92, 0xee, 0xc1, 0xdd, 0x39, 0x94, 0xa9, 0xb2, 0x5f, 0x15, 0xd8, 0x6a, 0x0b, 0x6a, 0xe1, - 0x78, 0x82, 0x22, 0xa9, 0xd6, 0x13, 0xf4, 0xc5, 0x2b, 0x84, 0x3d, 0x82, 0xdb, 0x28, 0xa4, 0x3b, - 0x0c, 0xbb, 0xc1, 0xc1, 0x01, 0xf1, 0xe3, 0xdb, 0xb8, 0x65, 0x44, 0x6d, 0x68, 0x24, 0x6d, 0x68, - 0x1c, 0xc4, 0x6d, 0xd8, 0x5a, 0xfd, 0xe5, 0x9f, 0x6d, 0xc5, 0x7a, 0x2b, 0x3d, 0x77, 0x10, 0x1c, - 0x5b, 0xac, 0xc0, 0xfb, 0xf0, 0x7e, 0xa9, 0xca, 0xc4, 0xcb, 0x95, 0x4c, 0xca, 0x95, 0x4c, 0xf5, - 0xa7, 0xb0, 0xd1, 0x16, 0xf4, 0x10, 0xaf, 0xe1, 0x6e, 0x9a, 0x69, 0xb9, 0x5c, 0xd3, 0x36, 0xbc, - 0x57, 0x98, 0x37, 0xad, 0xed, 0xb7, 0x57, 0x4b, 0x7b, 0xc4, 0xdd, 0x13, 0x22, 0xf1, 0xb1, 0x83, - 0x23, 0x19, 0x74, 0x71, 0x39, 0xf9, 0x3a, 0x44, 0x74, 0xf3, 0xb8, 0x67, 0xea, 0x91, 0x49, 0xfd, - 0xaa, 0x7a, 0x7c, 0x0f, 0x9b, 0x91, 0xee, 0xf8, 0x5c, 0xa2, 0x5b, 0x5c, 0x57, 0x93, 0xba, 0x0d, - 0x37, 0x05, 0x76, 0xbd, 0x8e, 0x37, 0xb1, 0xfb, 0xe8, 0xc7, 0xef, 0x0f, 0x82, 0xad, 0xa3, 0x70, - 0x27, 0x23, 0x7a, 0x07, 0xf4, 0x62, 0xe2, 0x44, 0xf1, 0xde, 0x7f, 0x15, 0x58, 0x69, 0x0b, 0xaa, - 0x3e, 0x85, 0x5b, 0x33, 0xa3, 0x52, 0xcf, 0x8c, 0xb8, 0xcc, 0xf0, 0xd1, 0x3e, 0x9c, 0x1f, 0x4f, - 0x2b, 0x82, 0xb0, 0x96, 0x1f, 0x4c, 0x77, 0xf3, 0x87, 0x73, 0x20, 0xed, 0xa3, 0x05, 0x40, 0x29, - 0x8d, 0x80, 0x5a, 0xe9, 0xf4, 0x69, 0x96, 0x25, 0xca, 0x63, 0xaf, 0x47, 0xfa, 0x03, 0xd4, 0x4a, - 0x07, 0x4c, 0x01, 0x69, 0x19, 0x56, 0xdb, 0x5b, 0x1c, 0x9b, 0x72, 0x4b, 0xd8, 0x2c, 0x99, 0x20, - 0x8d, 0x7c, 0xb6, 0x62, 0xa4, 0xf6, 0xf1, 0xa2, 0xc8, 0x94, 0xb5, 0x07, 0x6a, 0x41, 0x57, 0x7f, - 0x90, 0xcf, 0x93, 0x47, 0x69, 0xf7, 0x17, 0x41, 0x15, 0xf8, 0xcb, 0xb6, 0x71, 0xb9, 0xbf, 0x0c, - 0x72, 0x8e, 0xbf, 0xb2, 0xfe, 0xed, 0xc3, 0xdb, 0x45, 0x5d, 0x7a, 0xaf, 0x50, 0x7a, 0x16, 0xa6, - 0x3d, 0x58, 0x08, 0x96, 0x90, 0x69, 0x37, 0x9e, 0x07, 0x9f, 0x0a, 0xad, 0x83, 0x17, 0xe7, 0xba, - 0xf2, 0xf2, 0x5c, 0x57, 0xfe, 0x3d, 0xd7, 0x95, 0x9f, 0x2f, 0xf4, 0xa5, 0x97, 0x17, 0xfa, 0xd2, - 0x5f, 0x17, 0xfa, 0xd2, 0x77, 0xcd, 0x85, 0xbe, 0x14, 0xa4, 0xef, 0xa1, 0xb0, 0x2b, 0xe1, 0xf0, - 0xff, 0xe4, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x57, 0x44, 0xcb, 0x00, 0x01, 0x0a, 0x00, 0x00, + // 919 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcf, 0x73, 0xdb, 0x44, + 0x14, 0x8e, 0x92, 0x34, 0xc5, 0xaf, 0x85, 0x34, 0x6a, 0x92, 0x3a, 0x82, 0x2a, 0xc1, 0xa5, 0x8c, + 0x31, 0xad, 0x45, 0x02, 0xc3, 0x30, 0xb9, 0xd5, 0x0d, 0xa4, 0x9d, 0x8e, 0x67, 0x32, 0x0a, 0x74, + 0x06, 0x2e, 0x9e, 0x95, 0xf4, 0xba, 0xd6, 0x24, 0xb6, 0x94, 0xdd, 0x75, 0x88, 0x38, 0x75, 0x18, + 0x4e, 0x9c, 0x38, 0xf2, 0x07, 0x70, 0xe0, 0x98, 0x03, 0x7f, 0x44, 0x0f, 0x1c, 0x3a, 0x9c, 0x38, + 0x01, 0x13, 0x1f, 0xf2, 0x6f, 0x30, 0x92, 0x56, 0x72, 0xac, 0x1f, 0x8e, 0xd3, 0x4b, 0xe2, 0xdd, + 0xf7, 0xed, 0xfb, 0xbe, 0xef, 0x59, 0xfb, 0x59, 0xb0, 0xfa, 0x82, 0xb8, 0x2c, 0x60, 0x6e, 0x9f, + 0x1a, 0x3e, 0xfa, 0x86, 0x38, 0x69, 0xfa, 0xcc, 0x13, 0x9e, 0xfa, 0x76, 0xba, 0xdf, 0xf4, 0xd1, + 0xd7, 0x96, 0x48, 0xcf, 0xed, 0x7b, 0x46, 0xf4, 0x37, 0x46, 0x68, 0x77, 0x6c, 0x8f, 0xf7, 0x3c, + 0x6e, 0xf4, 0x38, 0x35, 0x8e, 0x37, 0xc3, 0x7f, 0xb2, 0xb0, 0x16, 0x17, 0x3a, 0xd1, 0xca, 0x88, + 0x17, 0xb2, 0xa4, 0x53, 0xcf, 0xa3, 0x87, 0x68, 0x44, 0x2b, 0x6b, 0xf0, 0xc2, 0x70, 0x06, 0x8c, + 0x08, 0xd7, 0xeb, 0xcb, 0xfa, 0x32, 0xf5, 0xa8, 0x17, 0x9f, 0x0b, 0x3f, 0xc9, 0x5d, 0x6d, 0x5c, + 0xa3, 0x4f, 0x18, 0xe9, 0x25, 0x1d, 0xeb, 0xe3, 0x35, 0x42, 0x29, 0x43, 0x4a, 0x04, 0x3a, 0x9d, + 0x03, 0x0c, 0x3a, 0xbc, 0x4b, 0x18, 0x26, 0xdc, 0x52, 0xaf, 0x45, 0x38, 0x1a, 0xc7, 0x9b, 0x16, + 0x0a, 0xb2, 0x69, 0xd8, 0x9e, 0x2b, 0xb9, 0x6b, 0x7f, 0x2a, 0xb0, 0xd8, 0xe6, 0xf4, 0x1b, 0xdf, + 0x21, 0x02, 0xf7, 0x22, 0x0e, 0xf5, 0x73, 0xa8, 0x90, 0x81, 0xe8, 0x7a, 0xcc, 0x15, 0x41, 0x55, + 0xd9, 0x50, 0xea, 0x95, 0x56, 0xf5, 0xaf, 0x3f, 0x1e, 0x2e, 0x4b, 0x53, 0x8f, 0x1c, 0x87, 0x21, + 0xe7, 0xfb, 0x22, 0xe4, 0x37, 0x47, 0x50, 0xf5, 0x0b, 0x58, 0x88, 0x55, 0x56, 0x67, 0x37, 0x94, + 0xfa, 0x8d, 0xad, 0x95, 0xe6, 0xd8, 0x38, 0x9b, 0x71, 0xfb, 0x56, 0xe5, 0xd5, 0x3f, 0xeb, 0x33, + 0xbf, 0x9f, 0x9f, 0x36, 0x14, 0x53, 0xe2, 0xb7, 0x77, 0x7f, 0x3c, 0x3f, 0x6d, 0x8c, 0x3a, 0xfd, + 0x7c, 0x7e, 0xda, 0xf8, 0x8c, 0xba, 0xa2, 0x3b, 0xb0, 0x9a, 0xb6, 0xd7, 0x33, 0xbe, 0x22, 0x2e, + 0xb3, 0x0e, 0x3d, 0xfb, 0xc0, 0x18, 0xf9, 0x3e, 0x89, 0x9c, 0x67, 0xa4, 0xd7, 0xd6, 0xe0, 0x4e, + 0x66, 0xcb, 0x44, 0xee, 0x7b, 0x7d, 0x8e, 0xb5, 0x97, 0x0a, 0x2c, 0xb7, 0x39, 0xdd, 0x1f, 0x58, + 0x3d, 0x57, 0x7c, 0xd9, 0xb7, 0x59, 0xe0, 0x0b, 0x74, 0xbe, 0x3e, 0x51, 0xab, 0x70, 0xdd, 0x66, + 0x48, 0x84, 0xc7, 0x62, 0xb3, 0x66, 0xb2, 0x54, 0x55, 0x98, 0x77, 0x88, 0x20, 0x91, 0x9d, 0x8a, + 0x19, 0x7d, 0x56, 0x1f, 0xc0, 0x92, 0x20, 0x8c, 0xa2, 0x68, 0x85, 0x82, 0x9e, 0xa0, 0x4b, 0xbb, + 0xa2, 0x3a, 0xb7, 0xa1, 0xd4, 0xe7, 0xcd, 0x7c, 0x61, 0xfb, 0x66, 0x68, 0x2c, 0xe9, 0x57, 0xf3, + 0xe1, 0xdd, 0x54, 0xc1, 0x2e, 0xf6, 0x91, 0x91, 0xc3, 0x37, 0x17, 0xb2, 0x02, 0x0b, 0x0c, 0x8f, + 0x3a, 0xae, 0x13, 0xb1, 0x57, 0xcc, 0x6b, 0x0c, 0x8f, 0x9e, 0x3a, 0x19, 0x46, 0x1d, 0xde, 0x2b, + 0xf2, 0x9c, 0x0e, 0xe5, 0x28, 0x52, 0xf4, 0x38, 0x44, 0xe3, 0xa3, 0xf4, 0x29, 0x7a, 0x86, 0xc1, + 0x7e, 0xf8, 0x0c, 0x4d, 0x50, 0xb4, 0x0a, 0x0b, 0xdd, 0xd8, 0xfb, 0x6c, 0xe4, 0x5d, 0xae, 0x52, + 0xa5, 0x73, 0x23, 0xa5, 0x19, 0x49, 0xf7, 0xe1, 0xde, 0x04, 0xca, 0x54, 0xd9, 0x6f, 0x0a, 0xac, + 0xb5, 0x39, 0x35, 0xf1, 0x68, 0x80, 0x3c, 0x99, 0xd6, 0x33, 0x0c, 0xf8, 0x25, 0xc2, 0x9e, 0xc0, + 0x22, 0x72, 0xe1, 0xf6, 0xa2, 0xdb, 0xe0, 0xe0, 0x21, 0x09, 0xe4, 0xd3, 0xb8, 0xd6, 0x8c, 0xaf, + 0x61, 0x33, 0xb9, 0x86, 0xcd, 0x1d, 0x79, 0x0d, 0x5b, 0xf3, 0xbf, 0xfe, 0xbb, 0xae, 0x98, 0xef, + 0xa4, 0xe7, 0x76, 0xc2, 0x63, 0xd3, 0x0d, 0x78, 0x1b, 0xde, 0x2f, 0x55, 0x99, 0x78, 0xb9, 0xd0, + 0x49, 0xb9, 0xd0, 0xa9, 0xf6, 0x1c, 0x56, 0xda, 0x9c, 0xee, 0xe2, 0x15, 0xdc, 0x8d, 0x3a, 0xcd, + 0x96, 0x6b, 0x5a, 0x87, 0xbb, 0x85, 0x7d, 0xd3, 0xd9, 0x7e, 0x7b, 0x71, 0xb4, 0x7b, 0xcc, 0x3d, + 0x26, 0x02, 0x9f, 0x3a, 0xd8, 0x17, 0xe1, 0x2d, 0x2e, 0x27, 0x5f, 0x86, 0x98, 0x6e, 0x12, 0xf7, + 0xd8, 0x3c, 0x32, 0xad, 0x2f, 0x9b, 0xc7, 0xf7, 0xb0, 0x1a, 0xeb, 0x96, 0xe7, 0x12, 0xdd, 0xfc, + 0xaa, 0x9a, 0xd4, 0x75, 0xb8, 0xc1, 0xd1, 0xf6, 0x3b, 0xfe, 0xc0, 0x3a, 0xc0, 0x40, 0x7e, 0x7f, + 0x10, 0x6e, 0xed, 0x45, 0x3b, 0x19, 0xd1, 0x1b, 0xa0, 0x17, 0x13, 0xa7, 0x13, 0xfb, 0x49, 0x81, + 0xdb, 0x91, 0x2f, 0xea, 0x72, 0x81, 0xec, 0xb1, 0xd7, 0x17, 0x8c, 0xd8, 0x62, 0x82, 0xb0, 0x8f, + 0xe0, 0x96, 0x2d, 0x51, 0x1d, 0x12, 0x27, 0xa6, 0xd4, 0xb8, 0x98, 0xec, 0xcb, 0x20, 0x55, 0x35, + 0x78, 0xcb, 0x95, 0x23, 0x92, 0x52, 0xd3, 0x75, 0x46, 0xe8, 0xdd, 0xe8, 0xba, 0x66, 0x55, 0x24, + 0x2a, 0xb7, 0x86, 0xd7, 0x61, 0xae, 0xcd, 0xa9, 0xfa, 0x1c, 0x6e, 0x8e, 0x05, 0xba, 0x9e, 0x09, + 0xe2, 0x4c, 0x44, 0x6a, 0x1f, 0x4e, 0xae, 0xa7, 0xdf, 0x1b, 0xc2, 0x52, 0x3e, 0x3e, 0xef, 0xe5, + 0x0f, 0xe7, 0x40, 0xda, 0xc7, 0x53, 0x80, 0x52, 0x1a, 0x0e, 0xd5, 0xd2, 0x8c, 0x6c, 0x94, 0x35, + 0xca, 0x63, 0xaf, 0x46, 0xfa, 0x03, 0x54, 0x4b, 0x63, 0xb0, 0x80, 0xb4, 0x0c, 0xab, 0x6d, 0x4d, + 0x8f, 0x4d, 0xb9, 0x05, 0xac, 0x96, 0xe4, 0x5c, 0x3d, 0xdf, 0xad, 0x18, 0xa9, 0x7d, 0x32, 0x2d, + 0x32, 0x65, 0xed, 0x82, 0x5a, 0x90, 0x3d, 0x1f, 0xe4, 0xfb, 0xe4, 0x51, 0xda, 0x83, 0x69, 0x50, + 0x05, 0xfe, 0xb2, 0x61, 0x53, 0xee, 0x2f, 0x83, 0x9c, 0xe0, 0xaf, 0x2c, 0x65, 0x0e, 0xe0, 0x76, + 0x51, 0x96, 0xdc, 0x2f, 0x94, 0x9e, 0x85, 0x69, 0x0f, 0xa7, 0x82, 0xa5, 0x64, 0x16, 0xdc, 0xca, + 0x85, 0x43, 0xad, 0x48, 0xf2, 0x38, 0x46, 0x6b, 0x5c, 0x8e, 0x49, 0x38, 0xb4, 0x6b, 0x2f, 0xc3, + 0x97, 0xa6, 0xd6, 0xce, 0xab, 0x33, 0x5d, 0x79, 0x7d, 0xa6, 0x2b, 0xff, 0x9d, 0xe9, 0xca, 0x2f, + 0x43, 0x7d, 0xe6, 0xf5, 0x50, 0x9f, 0xf9, 0x7b, 0xa8, 0xcf, 0x7c, 0xd7, 0x98, 0xea, 0x9d, 0x49, + 0x04, 0x3e, 0x72, 0x6b, 0x21, 0xfa, 0x19, 0xfc, 0xf4, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x99, + 0x96, 0xdf, 0x02, 0x0b, 0x0b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -866,6 +969,7 @@ type MsgClient interface { GetGeneralKeyshare(ctx context.Context, in *MsgGetGeneralKeyshare, opts ...grpc.CallOption) (*MsgGetGeneralKeyshareResponse, error) RequestPrivateIdentity(ctx context.Context, in *MsgRequestPrivateIdentity, opts ...grpc.CallOption) (*MsgRequestPrivateIdentityResponse, error) GetPrivateKeyshares(ctx context.Context, in *MsgGetPrivateKeyshares, opts ...grpc.CallOption) (*MsgGetPrivateKeysharesResponse, error) + RegisterContract(ctx context.Context, in *MsgRegisterContract, opts ...grpc.CallOption) (*MsgRegisterContractResponse, error) } type msgClient struct { @@ -948,6 +1052,15 @@ func (c *msgClient) GetPrivateKeyshares(ctx context.Context, in *MsgGetPrivateKe return out, nil } +func (c *msgClient) RegisterContract(ctx context.Context, in *MsgRegisterContract, opts ...grpc.CallOption) (*MsgRegisterContractResponse, error) { + out := new(MsgRegisterContractResponse) + err := c.cc.Invoke(ctx, "/fairyring.pep.Msg/RegisterContract", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // UpdateParams defines a (governance) operation for updating the module @@ -961,6 +1074,7 @@ type MsgServer interface { GetGeneralKeyshare(context.Context, *MsgGetGeneralKeyshare) (*MsgGetGeneralKeyshareResponse, error) RequestPrivateIdentity(context.Context, *MsgRequestPrivateIdentity) (*MsgRequestPrivateIdentityResponse, error) GetPrivateKeyshares(context.Context, *MsgGetPrivateKeyshares) (*MsgGetPrivateKeysharesResponse, error) + RegisterContract(context.Context, *MsgRegisterContract) (*MsgRegisterContractResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -991,6 +1105,9 @@ func (*UnimplementedMsgServer) RequestPrivateIdentity(ctx context.Context, req * func (*UnimplementedMsgServer) GetPrivateKeyshares(ctx context.Context, req *MsgGetPrivateKeyshares) (*MsgGetPrivateKeysharesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetPrivateKeyshares not implemented") } +func (*UnimplementedMsgServer) RegisterContract(ctx context.Context, req *MsgRegisterContract) (*MsgRegisterContractResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterContract not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -1140,6 +1257,24 @@ func _Msg_GetPrivateKeyshares_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Msg_RegisterContract_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRegisterContract) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RegisterContract(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/fairyring.pep.Msg/RegisterContract", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RegisterContract(ctx, req.(*MsgRegisterContract)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "fairyring.pep.Msg", HandlerType: (*MsgServer)(nil), @@ -1176,6 +1311,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "GetPrivateKeyshares", Handler: _Msg_GetPrivateKeyshares_Handler, }, + { + MethodName: "RegisterContract", + Handler: _Msg_RegisterContract_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "fairyring/pep/tx.proto", @@ -1689,6 +1828,73 @@ func (m *MsgGetPrivateKeysharesResponse) MarshalToSizedBuffer(dAtA []byte) (int, return len(dAtA) - i, nil } +func (m *MsgRegisterContract) 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 *MsgRegisterContract) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterContract) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Identity) > 0 { + i -= len(m.Identity) + copy(dAtA[i:], m.Identity) + i = encodeVarintTx(dAtA, i, uint64(len(m.Identity))) + i-- + dAtA[i] = 0x1a + } + if len(m.ContractAddress) > 0 { + i -= len(m.ContractAddress) + copy(dAtA[i:], m.ContractAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.ContractAddress))) + i-- + dAtA[i] = 0x12 + } + 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] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRegisterContractResponse) 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 *MsgRegisterContractResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterContractResponse) 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 @@ -1923,6 +2129,36 @@ func (m *MsgGetPrivateKeysharesResponse) Size() (n int) { return n } +func (m *MsgRegisterContract) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ContractAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Identity) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRegisterContractResponse) 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 } @@ -3394,6 +3630,202 @@ func (m *MsgGetPrivateKeysharesResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgRegisterContract) 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: MsgRegisterContract: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterContract: 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 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 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", 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.ContractAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Identity", 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.Identity = 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 *MsgRegisterContractResponse) 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: MsgRegisterContractResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterContractResponse: 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 From 75844c679fe7b0ed4bba1b250181c102aa5b0aad Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Wed, 25 Sep 2024 10:40:29 -0400 Subject: [PATCH 04/41] Add store migrations --- x/keyshare/keeper/migrations.go | 6 ++++++ x/keyshare/migrations/v3/store.go | 27 ++++++++++++++++++++++++ x/keyshare/module/module.go | 5 ++++- x/pep/keeper/migrations.go | 6 ++++++ x/pep/migrations/v3/store.go | 34 +++++++++++++++++++++++++++++++ x/pep/module/module.go | 5 ++++- 6 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 x/keyshare/migrations/v3/store.go create mode 100644 x/pep/migrations/v3/store.go diff --git a/x/keyshare/keeper/migrations.go b/x/keyshare/keeper/migrations.go index 315cf27d..b6db9407 100644 --- a/x/keyshare/keeper/migrations.go +++ b/x/keyshare/keeper/migrations.go @@ -2,6 +2,7 @@ package keeper import ( v2 "github.com/Fairblock/fairyring/x/keyshare/migrations/v2" + v3 "github.com/Fairblock/fairyring/x/keyshare/migrations/v3" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -19,3 +20,8 @@ func NewMigrator(keeper Keeper) Migrator { func (m Migrator) Migrate1to2(ctx sdk.Context) error { return v2.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc) } + +// Migrate2to3 migrates from version 2 to 3. +func (m Migrator) Migrate2to3(ctx sdk.Context) error { + return v3.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc) +} diff --git a/x/keyshare/migrations/v3/store.go b/x/keyshare/migrations/v3/store.go new file mode 100644 index 00000000..a2104cce --- /dev/null +++ b/x/keyshare/migrations/v3/store.go @@ -0,0 +1,27 @@ +package v3 + +import ( + "cosmossdk.io/core/store" + "github.com/Fairblock/fairyring/x/keyshare/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// MigrateStore migrates the x/keyshare module state from the consensus version 1 to version 2. +func MigrateStore(ctx sdk.Context, storeService store.KVStoreService, cdc codec.BinaryCodec) error { + currParams := types.NewParams( + 463000, + []string{"fairy1r6q07ne3deq64ezcjwkedcfe6669f0ewpwnxy9"}, + types.DefaultMinimumBonded, + types.DefaultSlashFractionNoKeyShare, + types.DefaultSlashFractionWrongKeyShare, + types.DefaultMaxIdledBlock) + + bz, err := cdc.Marshal(&currParams) + if err != nil { + return err + } + + store := storeService.OpenKVStore(ctx) + return store.Set(types.ParamsKey, bz) +} diff --git a/x/keyshare/module/module.go b/x/keyshare/module/module.go index f08d5eb1..56174475 100644 --- a/x/keyshare/module/module.go +++ b/x/keyshare/module/module.go @@ -40,7 +40,7 @@ var ( ) // ConsensusVersion defines the current x/keyshare module consensus version. -const ConsensusVersion = 2 +const ConsensusVersion = 3 // ---------------------------------------------------------------------------- // AppModuleBasic @@ -139,6 +139,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil { panic(fmt.Errorf("failed to migrate x/%s from version 1 to 2: %w", types.ModuleName, err)) } + if err := cfg.RegisterMigration(types.ModuleName, 2, m.Migrate2to3); err != nil { + panic(fmt.Errorf("failed to migrate x/%s from version 2 to 3: %w", types.ModuleName, err)) + } } // RegisterInvariants registers the invariants of the module. If an invariant deviates from its predicted value, the InvariantRegistry triggers appropriate logic (most often the chain will be halted) diff --git a/x/pep/keeper/migrations.go b/x/pep/keeper/migrations.go index 1a7005d9..5bf4f525 100644 --- a/x/pep/keeper/migrations.go +++ b/x/pep/keeper/migrations.go @@ -2,6 +2,7 @@ package keeper import ( v2 "github.com/Fairblock/fairyring/x/pep/migrations/v2" + v3 "github.com/Fairblock/fairyring/x/pep/migrations/v3" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -19,3 +20,8 @@ func NewMigrator(keeper Keeper) Migrator { func (m Migrator) Migrate1to2(ctx sdk.Context) error { return v2.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc) } + +// Migrate2to3 migrates from version 2 to 3. +func (m Migrator) Migrate2to3(ctx sdk.Context) error { + return v3.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc) +} diff --git a/x/pep/migrations/v3/store.go b/x/pep/migrations/v3/store.go new file mode 100644 index 00000000..c4e1dc53 --- /dev/null +++ b/x/pep/migrations/v3/store.go @@ -0,0 +1,34 @@ +package v3 + +import ( + "cosmossdk.io/core/store" + "github.com/Fairblock/fairyring/x/pep/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// MigrateStore migrates the x/pep module state from the consensus version 1 to version 2. +func MigrateStore(ctx sdk.Context, storeService store.KVStoreService, cdc codec.BinaryCodec) error { + currParams := types.NewParams( + []string{"fairy1yhpqdugfmfuhlvekkurnkstf2vl82063ajmfe5", "fairy1r6q07ne3deq64ezcjwkedcfe6669f0ewpwnxy9"}, + []*types.TrustedCounterParty{ + { + ClientId: "07-tendermint-0", + ConnectionId: "connection-0", + ChannelId: "channel-1", + }, + }, + types.DefaultKeyshareChannelID, + &types.DefaultMinGasPrice, + true, + &types.DefaultKeysharePrice, + ) + + bz, err := cdc.Marshal(&currParams) + if err != nil { + return err + } + + store := storeService.OpenKVStore(ctx) + return store.Set(types.ParamsKey, bz) +} diff --git a/x/pep/module/module.go b/x/pep/module/module.go index 7282a2dc..7b7cce83 100644 --- a/x/pep/module/module.go +++ b/x/pep/module/module.go @@ -53,7 +53,7 @@ var ( ) // ConsensusVersion defines the current x/pep module consensus version. -const ConsensusVersion = 2 +const ConsensusVersion = 3 // ---------------------------------------------------------------------------- // AppModuleBasic @@ -156,6 +156,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil { panic(fmt.Errorf("failed to migrate x/%s from version 1 to 2: %w", types.ModuleName, err)) } + if err := cfg.RegisterMigration(types.ModuleName, 2, m.Migrate2to3); err != nil { + panic(fmt.Errorf("failed to migrate x/%s from version 2 to 3: %w", types.ModuleName, err)) + } } // RegisterInvariants registers the invariants of the module. If an invariant deviates from its predicted value, the InvariantRegistry triggers appropriate logic (most often the chain will be halted) From 57101ca581b96204989abe6938e345c0fe7a313c Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Wed, 25 Sep 2024 10:40:38 -0400 Subject: [PATCH 05/41] Fix error after chain upgrade --- app/app.go | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/app/app.go b/app/app.go index 700ea28e..7421accf 100644 --- a/app/app.go +++ b/app/app.go @@ -7,20 +7,6 @@ import ( "os" "path/filepath" - upgradetypes "cosmossdk.io/x/upgrade/types" - keysharemodule "github.com/Fairblock/fairyring/x/keyshare/module" - keysharemoduletypes "github.com/Fairblock/fairyring/x/keyshare/types" - pepmodule "github.com/Fairblock/fairyring/x/pep/module" - peptypes "github.com/Fairblock/fairyring/x/pep/types" - "github.com/cosmos/ibc-go/modules/capability" - capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" - interchainaccountsmodule "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts" - interchainaccountstypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/types" - ibcfeemodule "github.com/cosmos/ibc-go/v8/modules/apps/29-fee" - ibcfeetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types" - "github.com/cosmos/ibc-go/v8/modules/apps/transfer" - transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" - _ "cosmossdk.io/api/cosmos/tx/config/v1" // import for side-effects "cosmossdk.io/depinject" "cosmossdk.io/log" @@ -35,6 +21,7 @@ import ( _ "cosmossdk.io/x/nft/module" // import for side-effects _ "cosmossdk.io/x/upgrade" // import for side-effects upgradekeeper "cosmossdk.io/x/upgrade/keeper" + upgradetypes "cosmossdk.io/x/upgrade/types" "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" @@ -94,7 +81,6 @@ import ( _ "github.com/cosmos/ibc-go/v8/modules/apps/29-fee" // import for side-effects ibcfeekeeper "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/keeper" ibctransferkeeper "github.com/cosmos/ibc-go/v8/modules/apps/transfer/keeper" - ibcmodule "github.com/cosmos/ibc-go/v8/modules/core" ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" "github.com/skip-mev/block-sdk/v2/block" "github.com/skip-mev/block-sdk/v2/block/base" @@ -481,23 +467,28 @@ func New( app.sm.RegisterStoreDecoders() app.UpgradeKeeper.SetUpgradeHandler( - "v0.8.2-to-0.8.3-release", + "v0.8.3-to-0.9.0", func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { - - fromVM[capabilitytypes.ModuleName] = capability.AppModule{}.ConsensusVersion() - fromVM[peptypes.ModuleName] = pepmodule.AppModule{}.ConsensusVersion() - fromVM[keysharemoduletypes.ModuleName] = keysharemodule.AppModule{}.ConsensusVersion() - fromVM[ibcmodule.AppModule{}.Name()] = ibcmodule.AppModule{}.ConsensusVersion() - fromVM[ibcfeetypes.ModuleName] = ibcfeemodule.AppModule{}.ConsensusVersion() - fromVM[wasmtypes.ModuleName] = wasm.AppModule{}.ConsensusVersion() - fromVM[transfertypes.ModuleName] = transfer.AppModule{}.ConsensusVersion() - fromVM[interchainaccountstypes.ModuleName] = interchainaccountsmodule.AppModule{}.ConsensusVersion() - // 07-tendermint, 06-solomachine - return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) }, ) + upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() + if err != nil { + panic(err) + } + + if upgradeInfo.Name == "v0.8.3-to-0.9.0" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + storeUpgrades := storetypes.StoreUpgrades{ + Deleted: []string{ + "capability", + }, + } + + // configure store loader that checks if version == upgradeHeight and applies store upgrades + app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) + } + // A custom InitChainer can be set if extra pre-init-genesis logic is required. // By default, when using app wiring enabled module, this is not required. // For instance, the upgrade module will set automatically the module version map in its init genesis thanks to app wiring. From 02ea80730918472c0831bc012e3dda44f282099e Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Wed, 25 Sep 2024 10:40:56 -0400 Subject: [PATCH 06/41] Include keyshare & pep tests in chain upgrade test script --- scripts/tests/TestChainUpgrade.sh | 248 +++++++++++++++++++++++++----- 1 file changed, 211 insertions(+), 37 deletions(-) diff --git a/scripts/tests/TestChainUpgrade.sh b/scripts/tests/TestChainUpgrade.sh index c57cb7df..066d64d3 100755 --- a/scripts/tests/TestChainUpgrade.sh +++ b/scripts/tests/TestChainUpgrade.sh @@ -4,8 +4,8 @@ WORKING_DIR="$HOME/.chain_upgrade_test_env" GIT_FAIRYRING_REPO=https://github.com/Fairblock/fairyring.git GO_VERSION_FROM=system GO_VERSION_TO=system -GIT_TAG_UPGRADE_FROM=v0.8.2 -GIT_TAG_UPGRADE_TO=0.8.3-release +GIT_TAG_UPGRADE_FROM=v0.8.3 +GIT_TAG_UPGRADE_TO=main BINARY=fairyringd BINARY_FULL_PATH=$WORKING_DIR/$GIT_TAG_UPGRADE_FROM/build/$BINARY @@ -14,39 +14,40 @@ UPGRADER=cosmovisor ################## # Setup Binaries # ################## - -echo "This script require 'cosmovisor' and 'gvm' installed" - -echo "Cleaning up the testing environment" -rm -rf $WORKING_DIR &> /dev/null - -echo "Creating testing environment: $WORKING_DIR" -if ! mkdir -p $WORKING_DIR 2>/dev/null; then - echo "Failed to create chain upgrade testing environment. Aborting..." - exit 1 -fi - -echo "Cloning $BINARY repo" -if ! cd "$WORKING_DIR" 2>/dev/null; then - echo "Failed to change dir to $WORKING_DIR. Aborting..." -fi - -[[ -s "$GVM_ROOT/scripts/gvm" ]] && source "$GVM_ROOT/scripts/gvm" - -echo "Installing $GIT_TAG_UPGRADE_FROM $BINARY" -git clone $GIT_FAIRYRING_REPO $GIT_TAG_UPGRADE_FROM -cd "$WORKING_DIR/$GIT_TAG_UPGRADE_FROM" -git checkout $GIT_TAG_UPGRADE_FROM -echo "Building the 'Upgrade From' $BINARY" -gvm use $GO_VERSION_FROM -go mod tidy -make build - -echo "Installing $GIT_TAG_UPGRADE_TO $BINARY" -cd "$WORKING_DIR" -git clone $GIT_FAIRYRING_REPO $GIT_TAG_UPGRADE_TO +# +#echo "This script require 'cosmovisor' and 'gvm' installed" +# +#echo "Cleaning up the testing environment" +#rm -rf $WORKING_DIR &> /dev/null +# +#echo "Creating testing environment: $WORKING_DIR" +#if ! mkdir -p $WORKING_DIR 2>/dev/null; then +# echo "Failed to create chain upgrade testing environment. Aborting..." +# exit 1 +#fi +# +#echo "Cloning $BINARY repo" +#if ! cd "$WORKING_DIR" 2>/dev/null; then +# echo "Failed to change dir to $WORKING_DIR. Aborting..." +#fi +# +#[[ -s "$GVM_ROOT/scripts/gvm" ]] && source "$GVM_ROOT/scripts/gvm" +# +#echo "Installing $GIT_TAG_UPGRADE_FROM $BINARY" +#git clone $GIT_FAIRYRING_REPO $GIT_TAG_UPGRADE_FROM +#cd "$WORKING_DIR/$GIT_TAG_UPGRADE_FROM" +#git checkout $GIT_TAG_UPGRADE_FROM +#echo "Building the 'Upgrade From' $BINARY" +#gvm use $GO_VERSION_FROM +#go mod tidy +#make build + +#echo "Installing $GIT_TAG_UPGRADE_TO $BINARY" +#cd "$WORKING_DIR" +#git clone $GIT_FAIRYRING_REPO $GIT_TAG_UPGRADE_TO cd "$WORKING_DIR/$GIT_TAG_UPGRADE_TO" -git checkout $GIT_TAG_UPGRADE_TO +echo $GIT_TAG_UPGRADE_TO +#git checkout $GIT_TAG_UPGRADE_TO echo "Building the 'Upgrade To' $BINARY" gvm use $GO_VERSION_TO go mod tidy @@ -75,9 +76,9 @@ cat <<< $(jq '.app_state.gov.params.expedited_voting_period = "10s"' $CHAIN_HOME $BINARY_FULL_PATH keys add validator --keyring-backend test --home $CHAIN_HOME $BINARY_FULL_PATH keys add wallet1 --keyring-backend test --home $CHAIN_HOME -$BINARY_FULL_PATH genesis add-genesis-account validator 100000000000stake --keyring-backend test --home $CHAIN_HOME -$BINARY_FULL_PATH genesis add-genesis-account wallet1 100000000000stake --keyring-backend test --home $CHAIN_HOME -$BINARY_FULL_PATH genesis gentx validator 1000000stake --chain-id $CHAIN_ID --keyring-backend test --home $CHAIN_HOME +$BINARY_FULL_PATH genesis add-genesis-account validator 100000000000ufairy,10000000000000stake --keyring-backend test --home $CHAIN_HOME +$BINARY_FULL_PATH genesis add-genesis-account wallet1 100000000000ufairy,10000000000000stake --keyring-backend test --home $CHAIN_HOME +$BINARY_FULL_PATH genesis gentx validator 10000000000stake --chain-id $CHAIN_ID --keyring-backend test --home $CHAIN_HOME $BINARY_FULL_PATH genesis collect-gentxs --home $CHAIN_HOME export DAEMON_NAME=$BINARY @@ -86,6 +87,11 @@ export DAEMON_RESTART_AFTER_UPGRADE=true $UPGRADER init $WORKING_DIR/$GIT_TAG_UPGRADE_FROM/build/$BINARY +VALIDATOR_1=$($BINARY keys show validator -a --keyring-backend test --home $CHAIN_HOME) +sed -i -e 's/"trusted_addresses": \[\]/"trusted_addresses": \["'"$VALIDATOR_1"'"\]/g' $CHAIN_HOME/config/genesis.json +sed -i -e 's/"key_expiry": "100"/"key_expiry": "10000"/g' $CHAIN_HOME/config/genesis.json +sed -i -e 's/"is_source_chain": false/"is_source_chain": true/g' $CHAIN_HOME/config/genesis.json + $UPGRADER run start --home $CHAIN_HOME --log_format json > $WORKING_DIR/$GIT_TAG_UPGRADE_FROM.log 2>&1 & ####################### @@ -168,4 +174,172 @@ sleep 6 echo "Sequence after tx: $($BINARY_FULL_PATH q auth account $WAL1_ADDR -o json | jq -r '.account.value.sequence'), Balance after tx: $($BINARY_FULL_PATH q bank balances $VAL_ADDR -o json | jq -r '.balances[0]')" +BINARY=$BINARY_FULL_PATH +CHAINID_1=$CHAIN_ID +BLOCK_TIME=6 + +WALLET_1=$($BINARY keys show wallet1 -a --keyring-backend test --home $CHAIN_HOME) +VALIDATOR_1=$($BINARY keys show validator -a --keyring-backend test --home $CHAIN_HOME) + +check_tx_code () { + local TX_CODE=$(echo "$1" | jq -r '.code') + if [ "$TX_CODE" != 0 ]; then + echo "ERROR: Tx failed with code: $TX_CODE" + exit 1 + fi +} + +wait_for_tx () { + sleep $BLOCK_TIME + local TXHASH=$(echo "$1" | jq -r '.txhash') + RESULT=$($BINARY q tx --type=hash $TXHASH --home $CHAIN_HOME --chain-id $CHAINID_1 -o json) + echo "$RESULT" +} + + +echo "Staked account registering as a validator on chain $CHAINID_1" +RESULT=$($BINARY tx keyshare register-validator --from $VALIDATOR_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT +RESULT=$(wait_for_tx $RESULT) +VALIDATOR_ADDR=$(echo "$RESULT" | jq '.events' | jq 'map(select(any(.type; contains("validator"))))[]' | jq '.attributes' | jq 'map(select(any(.key; contains("creator"))))[]' | jq -r '.value') +if [ "$VALIDATOR_ADDR" != "$VALIDATOR_1" ]; then + echo "ERROR: KeyShare module register validator error. Expected registered validator address '$VALIDATOR_1', got '$VALIDATOR_ADDR'" + echo "ERROR MESSAGE: $(echo "$RESULT" | jq -r '.raw_log')" + exit 1 +fi + +GENERATED_RESULT=$($BINARY share-generation generate 1 1) +GENERATED_SHARE=$(echo "$GENERATED_RESULT" | jq -r '.Shares[0].Value') +PUB_KEY=$(echo "$GENERATED_RESULT" | jq -r '.MasterPublicKey') +COMMITS=$(echo "$GENERATED_RESULT" | jq -r '.Commitments[0]') + +echo "Trusted address submit pub key on chain $CHAINID_1" +RESULT=$($BINARY tx keyshare create-latest-pub-key $PUB_KEY $COMMITS 1 '[{"data":"'"$GENERATED_SHARE"'","validator":"'"$VALIDATOR_1"'"}]' --from $VALIDATOR_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT +RESULT=$(wait_for_tx $RESULT) +VALIDATOR_ADDR=$(echo "$RESULT" | jq '.events' | jq 'map(select(any(.type; contains("pubkey"))))[]' | jq '.attributes' | jq 'map(select(any(.key; contains("creator"))))[]' | jq -r '.value') +if [ "$VALIDATOR_ADDR" != "$VALIDATOR_1" ]; then + echo "ERROR: KeyShare module submit pub key from trusted address error. Expected creator address '$VALIDATOR_1', got '$VALIDATOR_ADDR'" + echo "ERROR MESSAGE: $(echo "$RESULT" | jq -r '.raw_log')" + exit 1 +fi + +CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_HOME -o json | jq -r '.block.header.height') +TARGET_HEIGHT=$((CURRENT_BLOCK+1)) +EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $TARGET_HEIGHT) +EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') + +echo "Registered validator submit valid key share on chain $CHAINID_1" +RESULT=$($BINARY tx keyshare send-keyshare $EXTRACTED_SHARE 1 $TARGET_HEIGHT --from $VALIDATOR_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT +RESULT=$(wait_for_tx $RESULT) +AGGRED_SHARE=$(echo "$RESULT" | jq '.events' | jq 'map(select(any(.type; contains("keyshare-aggregated"))))[]' | jq '.attributes' | jq 'map(select(any(.key; contains("data"))))[]' | jq -r '.value') +if [ "$AGGRED_SHARE" != $EXTRACTED_SHARE ]; then + echo "ERROR: KeyShare module submit valid key share from registered validator error. Expected the aggregated key to be $EXTRACTED_SHARE, got '$AGGRED_SHARE'" + echo "ERROR MESSAGE: $(echo "$RESULT" | jq -r '.raw_log')" + echo $RESULT | jq +exit 1 +fi + +./scripts/tests/keyshareSender.sh $BINARY $CHAIN_HOME tcp://localhost:26657 $VALIDATOR_1 $CHAINID_1 > $WORKING_DIR/keyshareSender.log 2>&1 & + + +echo "Query submitted key share on chain $CHAINID_1" +RESULT=$($BINARY query keyshare list-key-share -o json) +RESULT_SENDER=$(echo "$RESULT" | jq -r '.keyShare[0].validator') +RESULT_KEYSHARE=$(echo "$RESULT" | jq -r '.keyShare[0].keyShare') +RESULT_HEIGHT=$(echo "$RESULT" | jq -r '.keyShare[0].blockHeight') +if [ "$RESULT_SENDER" != "$VALIDATOR_1" ] && [ "$RESULT_KEYSHARE" != "$EXTRACTED_SHARE" ] && [ "$RESULT_HEIGHT" != "$TARGET_HEIGHT" ]; then + echo "ERROR: KeyShare module query submitted key share error, Expected to get the submitted key share, got '$RESULT'" + echo $RESULT | jq +exit 1 +fi +echo "Key Share Successfully submitted: '$RESULT_KEYSHARE' for height '$RESULT_HEIGHT'" + + +echo "Query aggregated key share on chain $CHAINID_1" +RESULT=$($BINARY query keyshare list-aggregated-key-share -o json) +RESULT_HEIGHT=$(echo "$RESULT" | jq -r '.aggregatedKeyShare[0].height') +RESULT_DATA=$(echo "$RESULT" | jq -r '.aggregatedKeyShare[0].data') +if [ "$RESULT_HEIGHT" != "$TARGET_HEIGHT" ]; then + echo "ERROR: KeyShare module aggregate key share error. Expected to get an aggregated key, got '$RESULT'" + echo $RESULT | jq +exit 1 +fi +echo "Key Share Successfully aggregated: '$RESULT_DATA'" + +# PEP + +echo "Query account pep nonce before submitting encrypted tx from pep module on chain $CHAINID_1" +RESULT=$($BINARY query pep show-pep-nonce $VALIDATOR_1 --home $CHAIN_HOME --chain-id $CHAINID_1 -o json) +VALIDATOR_PEP_NONCE_BEFORE=$(echo "$RESULT" | jq -r '.pepNonce.nonce') +if [ "$VALIDATOR_PEP_NONCE_BEFORE" != "1" ]; then + echo "ERROR: Pep module query Pep Nonce error. Expected Pep Nonce to be 1, got '$VALIDATOR_PEP_NONCE'" + echo "ERROR MESSAGE: $(echo "$RESULT" | jq -r '.raw_log')" + exit 1 +fi + + +echo "Query target account token balance before submitting encrypted tx from pep module on chain $CHAINID_1" +RESULT=$($BINARY query bank balances $WALLET_1 -o json) +echo $RESULT +echo $TARGET_BAL_DENOM +TARGET_BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') +TARGET_BAL=$(echo "$RESULT" | jq -r '.balances[0].amount') +echo "Target account has: $TARGET_BAL $TARGET_BAL_DENOM before encrypted bank send tx" + + +echo "Signing bank send tx with pep nonce: '$VALIDATOR_PEP_NONCE_BEFORE'" +echo "Sending 1 $TARGET_BAL_DENOM to target address" +$BINARY tx bank send $VALIDATOR_1 $WALLET_1 1$TARGET_BAL_DENOM --from $VALIDATOR_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --keyring-backend test --generate-only -o json -y > unsigned.json +SIGNED_DATA=$($BINARY tx sign unsigned.json --from $VALIDATOR_1 --offline --account-number 0 --sequence $VALIDATOR_PEP_NONCE_BEFORE --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --keyring-backend test -y) + +CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_HOME -o json | jq -r '.block.header.height') +TARGET_BLOCK=$(($CURRENT_BLOCK+5)) +echo "Encrypting signed tx with Pub key: '$PUB_KEY'" +CIPHER=$($BINARY encrypt $TARGET_BLOCK "" $SIGNED_DATA --node $CHAIN1_NODE) + +rm -r unsigned.json &> /dev/null + +RESULT=$($BINARY query bank balances $VALIDATOR_1 -o json) +BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') +BAL_AMT=$(echo "$RESULT" | jq -r '.balances[0].amount') +echo "Balance before submitting encrypted tx: $BAL_AMT$BAL_DENOM" + + +echo "Submit encrypted tx to pep module on chain $CHAINID_1" +RESULT=$($BINARY tx pep submit-encrypted-tx $CIPHER $TARGET_BLOCK --from $VALIDATOR_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_HOME --chain-id $CHAINID_1 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT +RESULT=$(wait_for_tx $RESULT) +TARGET_HEIGHT=$(echo "$RESULT" | jq '.events' | jq 'map(select(any(.type; contains("new-encrypted-tx-submitted"))))[]' | jq '.attributes' | jq 'map(select(any(.key; contains("height"))))[]' | jq -r '.value') +if [ "$TARGET_HEIGHT" != "$TARGET_BLOCK" ]; then + echo "ERROR: Pep module submit encrypted tx error. Expected tx to submitted without error with target height '$TARGET_BLOCK', got '$TARGET_HEIGHT' and '$EVENT_TYPE' | '$CURRENT_BLOCK'" + echo "ERROR MESSAGE: $(echo "$RESULT" | jq -r '.raw_log')" + echo "ERROR MESSAGE: $(echo "$RESULT" | jq '.')" + echo $RESULT | jq + exit 1 +fi + + +RESULT=$($BINARY query bank balances $VALIDATOR_1 -o json) +BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') +BAL_AMT=$(echo "$RESULT" | jq -r '.balances[0].amount') +echo "Balance after submitting first encrypted tx: $BAL_AMT$BAL_DENOM" + + +echo "Query target account token balance after encrypted tx being executed from pep module on chain $CHAINID_1" +RESULT=$($BINARY query bank balances $WALLET_1 -o json) +TARGET_BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') +TARGET_BAL_AFTER=$(echo "$RESULT" | jq -r '.balances[0].amount') +echo "Target account has: $TARGET_BAL_AFTER $TARGET_BAL_DENOM after encrypted bank send tx being executed, balance increased $(($TARGET_BAL_AFTER - $TARGET_BAL)) $TARGET_BAL_DENOM" +if [ "$TARGET_BAL_AFTER" == "$TARGET_BAL" ]; then + echo "ERROR: Pep module encrypted tx execution error. Expected Target Balance to be updated, got same balance: '$TARGET_BAL_AFTER $TARGET_BAL_DENOM'" + exit 1 +fi + +RESULT=$($BINARY query bank balances $VALIDATOR_1 -o json) +BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') +BAL_AMT=$(echo "$RESULT" | jq -r '.balances[0].amount') +echo "Balance after encrypted tx execution: $BAL_AMT$BAL_DENOM" + echo "Run 'pkill fairyringd' later to stop fairyring" \ No newline at end of file From 1c4f5f28a42cd281b3bb2736f512527c3206b2c2 Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Wed, 25 Sep 2024 20:13:56 +0530 Subject: [PATCH 07/41] minor fix --- app/app.go | 3 --- app/pep.go | 3 ++- testutil/keeper/pep.go | 1 + x/pep/module/module.go | 1 + 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/app.go b/app/app.go index 700ea28e..45b5b594 100644 --- a/app/app.go +++ b/app/app.go @@ -86,12 +86,9 @@ import ( slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" _ "github.com/cosmos/cosmos-sdk/x/staking" // import for side-effects stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - _ "github.com/cosmos/ibc-go/modules/capability" // import for side-effects capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" - _ "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts" // import for side-effects icacontrollerkeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/keeper" icahostkeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/keeper" - _ "github.com/cosmos/ibc-go/v8/modules/apps/29-fee" // import for side-effects ibcfeekeeper "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/keeper" ibctransferkeeper "github.com/cosmos/ibc-go/v8/modules/apps/transfer/keeper" ibcmodule "github.com/cosmos/ibc-go/v8/modules/core" diff --git a/app/pep.go b/app/pep.go index 45cfbe4c..a0878403 100644 --- a/app/pep.go +++ b/app/pep.go @@ -2,6 +2,7 @@ package app import ( storetypes "cosmossdk.io/store/types" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" pepmodulekeeper "github.com/Fairblock/fairyring/x/pep/keeper" pepmodule "github.com/Fairblock/fairyring/x/pep/module" peptypes "github.com/Fairblock/fairyring/x/pep/types" @@ -21,7 +22,7 @@ func (app *App) registerPepModule() (porttypes.IBCModule, error) { } scopedPepKeeper := app.CapabilityKeeper.ScopeToModule(peptypes.ModuleName) - contractKeeper := app.WasmKeeper.NewDefaultPermissionKeeper(&app.WasmKeeper) + contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(&app.WasmKeeper) // The last arguments can contain custom message handlers, and custom query handlers, // if we want to allow any custom callbacks diff --git a/testutil/keeper/pep.go b/testutil/keeper/pep.go index 9f2fed2c..caa6a606 100644 --- a/testutil/keeper/pep.go +++ b/testutil/keeper/pep.go @@ -60,6 +60,7 @@ func PepKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { scopedKeeper, nil, nil, + nil, ) ctx := sdk.NewContext(stateStore, cmtproto.Header{}, false, log.NewNopLogger()) diff --git a/x/pep/module/module.go b/x/pep/module/module.go index f79c2499..d6caaa7a 100644 --- a/x/pep/module/module.go +++ b/x/pep/module/module.go @@ -277,6 +277,7 @@ func (am AppModule) BeginBlock(cctx context.Context) error { continue } + // execute registered contracts contracts, found := am.keeper.GetContractEntriesByID(ctx, entry.Identity) if found { if len(contracts.Contracts) != 0 { From 1b5d4a07749acdcd900fb8b5f2cb3c28d736fcc8 Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Wed, 25 Sep 2024 21:32:07 -0400 Subject: [PATCH 08/41] Fix keyshare module being re init --- app/app.go | 25 +++++++++++++++++++++++-- x/keyshare/keeper/migrations.go | 6 ------ x/keyshare/migrations/v3/store.go | 27 --------------------------- x/keyshare/module/module.go | 2 +- x/pep/migrations/v3/store.go | 27 +++++++++++++++------------ 5 files changed, 39 insertions(+), 48 deletions(-) delete mode 100644 x/keyshare/migrations/v3/store.go diff --git a/app/app.go b/app/app.go index 7421accf..864af8e0 100644 --- a/app/app.go +++ b/app/app.go @@ -3,6 +3,19 @@ package app import ( "context" "fmt" + keysharemodule "github.com/Fairblock/fairyring/x/keyshare/module" + keysharemoduletypes "github.com/Fairblock/fairyring/x/keyshare/types" + pepmodule "github.com/Fairblock/fairyring/x/pep/module" + peptypes "github.com/Fairblock/fairyring/x/pep/types" + "github.com/cosmos/ibc-go/modules/capability" + capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" + interchainaccountsmodule "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts" + interchainaccountstypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/types" + ibcfeemodule "github.com/cosmos/ibc-go/v8/modules/apps/29-fee" + ibcfeetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types" + "github.com/cosmos/ibc-go/v8/modules/apps/transfer" + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + ibcmodule "github.com/cosmos/ibc-go/v8/modules/core" "io" "os" "path/filepath" @@ -467,8 +480,16 @@ func New( app.sm.RegisterStoreDecoders() app.UpgradeKeeper.SetUpgradeHandler( - "v0.8.3-to-0.9.0", + "v0.8.3-to-0.9.0-release", func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + fromVM[capabilitytypes.ModuleName] = capability.AppModule{}.ConsensusVersion() + fromVM[peptypes.ModuleName] = pepmodule.AppModule{}.ConsensusVersion() + fromVM[keysharemoduletypes.ModuleName] = keysharemodule.AppModule{}.ConsensusVersion() + fromVM[ibcmodule.AppModule{}.Name()] = ibcmodule.AppModule{}.ConsensusVersion() + fromVM[ibcfeetypes.ModuleName] = ibcfeemodule.AppModule{}.ConsensusVersion() + fromVM[wasmtypes.ModuleName] = wasm.AppModule{}.ConsensusVersion() + fromVM[transfertypes.ModuleName] = transfer.AppModule{}.ConsensusVersion() + fromVM[interchainaccountstypes.ModuleName] = interchainaccountsmodule.AppModule{}.ConsensusVersion() return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) }, ) @@ -478,7 +499,7 @@ func New( panic(err) } - if upgradeInfo.Name == "v0.8.3-to-0.9.0" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + if upgradeInfo.Name == "v0.8.3-to-0.9.0-release" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { storeUpgrades := storetypes.StoreUpgrades{ Deleted: []string{ "capability", diff --git a/x/keyshare/keeper/migrations.go b/x/keyshare/keeper/migrations.go index b6db9407..315cf27d 100644 --- a/x/keyshare/keeper/migrations.go +++ b/x/keyshare/keeper/migrations.go @@ -2,7 +2,6 @@ package keeper import ( v2 "github.com/Fairblock/fairyring/x/keyshare/migrations/v2" - v3 "github.com/Fairblock/fairyring/x/keyshare/migrations/v3" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -20,8 +19,3 @@ func NewMigrator(keeper Keeper) Migrator { func (m Migrator) Migrate1to2(ctx sdk.Context) error { return v2.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc) } - -// Migrate2to3 migrates from version 2 to 3. -func (m Migrator) Migrate2to3(ctx sdk.Context) error { - return v3.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc) -} diff --git a/x/keyshare/migrations/v3/store.go b/x/keyshare/migrations/v3/store.go deleted file mode 100644 index a2104cce..00000000 --- a/x/keyshare/migrations/v3/store.go +++ /dev/null @@ -1,27 +0,0 @@ -package v3 - -import ( - "cosmossdk.io/core/store" - "github.com/Fairblock/fairyring/x/keyshare/types" - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// MigrateStore migrates the x/keyshare module state from the consensus version 1 to version 2. -func MigrateStore(ctx sdk.Context, storeService store.KVStoreService, cdc codec.BinaryCodec) error { - currParams := types.NewParams( - 463000, - []string{"fairy1r6q07ne3deq64ezcjwkedcfe6669f0ewpwnxy9"}, - types.DefaultMinimumBonded, - types.DefaultSlashFractionNoKeyShare, - types.DefaultSlashFractionWrongKeyShare, - types.DefaultMaxIdledBlock) - - bz, err := cdc.Marshal(&currParams) - if err != nil { - return err - } - - store := storeService.OpenKVStore(ctx) - return store.Set(types.ParamsKey, bz) -} diff --git a/x/keyshare/module/module.go b/x/keyshare/module/module.go index 56174475..10c01465 100644 --- a/x/keyshare/module/module.go +++ b/x/keyshare/module/module.go @@ -40,7 +40,7 @@ var ( ) // ConsensusVersion defines the current x/keyshare module consensus version. -const ConsensusVersion = 3 +const ConsensusVersion = 2 // ---------------------------------------------------------------------------- // AppModuleBasic diff --git a/x/pep/migrations/v3/store.go b/x/pep/migrations/v3/store.go index c4e1dc53..d4b51a5b 100644 --- a/x/pep/migrations/v3/store.go +++ b/x/pep/migrations/v3/store.go @@ -9,18 +9,22 @@ import ( // MigrateStore migrates the x/pep module state from the consensus version 1 to version 2. func MigrateStore(ctx sdk.Context, storeService store.KVStoreService, cdc codec.BinaryCodec) error { + store := storeService.OpenKVStore(ctx) + currentParamsBytes, err := store.Get(types.ParamsKey) + if err != nil { + return err + } + var currentParams types.Params + if err = cdc.Unmarshal(currentParamsBytes, ¤tParams); err != nil { + return err + } + currParams := types.NewParams( - []string{"fairy1yhpqdugfmfuhlvekkurnkstf2vl82063ajmfe5", "fairy1r6q07ne3deq64ezcjwkedcfe6669f0ewpwnxy9"}, - []*types.TrustedCounterParty{ - { - ClientId: "07-tendermint-0", - ConnectionId: "connection-0", - ChannelId: "channel-1", - }, - }, - types.DefaultKeyshareChannelID, - &types.DefaultMinGasPrice, - true, + currentParams.TrustedAddresses, + currentParams.TrustedCounterParties, + currentParams.KeyshareChannelId, + currentParams.MinGasPrice, + currentParams.IsSourceChain, &types.DefaultKeysharePrice, ) @@ -29,6 +33,5 @@ func MigrateStore(ctx sdk.Context, storeService store.KVStoreService, cdc codec. return err } - store := storeService.OpenKVStore(ctx) return store.Set(types.ParamsKey, bz) } From 086393922ecfb9c1cb5b9a30f714a0ddaf39232e Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Wed, 25 Sep 2024 21:32:32 -0400 Subject: [PATCH 09/41] Fix script error and add general keyshare test --- scripts/tests/TestChainUpgrade.sh | 212 ++++++++++++++++++++++-------- 1 file changed, 160 insertions(+), 52 deletions(-) diff --git a/scripts/tests/TestChainUpgrade.sh b/scripts/tests/TestChainUpgrade.sh index 066d64d3..c15f98f2 100755 --- a/scripts/tests/TestChainUpgrade.sh +++ b/scripts/tests/TestChainUpgrade.sh @@ -5,49 +5,52 @@ GIT_FAIRYRING_REPO=https://github.com/Fairblock/fairyring.git GO_VERSION_FROM=system GO_VERSION_TO=system GIT_TAG_UPGRADE_FROM=v0.8.3 -GIT_TAG_UPGRADE_TO=main +GIT_TAG_UPGRADE_TO=0.9.0-release BINARY=fairyringd BINARY_FULL_PATH=$WORKING_DIR/$GIT_TAG_UPGRADE_FROM/build/$BINARY +NEW_BINARY_FULL_PATH=$WORKING_DIR/$GIT_TAG_UPGRADE_TO/build/$BINARY UPGRADER=cosmovisor +CURRENT_PATH=$(pwd) +BLOCK_TIME=6 ################## # Setup Binaries # ################## -# -#echo "This script require 'cosmovisor' and 'gvm' installed" -# -#echo "Cleaning up the testing environment" -#rm -rf $WORKING_DIR &> /dev/null -# -#echo "Creating testing environment: $WORKING_DIR" -#if ! mkdir -p $WORKING_DIR 2>/dev/null; then -# echo "Failed to create chain upgrade testing environment. Aborting..." -# exit 1 -#fi -# -#echo "Cloning $BINARY repo" -#if ! cd "$WORKING_DIR" 2>/dev/null; then -# echo "Failed to change dir to $WORKING_DIR. Aborting..." -#fi -# -#[[ -s "$GVM_ROOT/scripts/gvm" ]] && source "$GVM_ROOT/scripts/gvm" -# -#echo "Installing $GIT_TAG_UPGRADE_FROM $BINARY" -#git clone $GIT_FAIRYRING_REPO $GIT_TAG_UPGRADE_FROM -#cd "$WORKING_DIR/$GIT_TAG_UPGRADE_FROM" -#git checkout $GIT_TAG_UPGRADE_FROM -#echo "Building the 'Upgrade From' $BINARY" -#gvm use $GO_VERSION_FROM -#go mod tidy -#make build - -#echo "Installing $GIT_TAG_UPGRADE_TO $BINARY" -#cd "$WORKING_DIR" -#git clone $GIT_FAIRYRING_REPO $GIT_TAG_UPGRADE_TO + +echo "This script require 'cosmovisor' and 'gvm' installed" + +echo "Cleaning up the testing environment" +rm -rf $WORKING_DIR &> /dev/null + +echo "Creating testing environment: $WORKING_DIR" +if ! mkdir -p $WORKING_DIR 2>/dev/null; then + echo "Failed to create chain upgrade testing environment. Aborting..." + exit 1 +fi + +echo "Cloning $BINARY repo" +if ! cd "$WORKING_DIR" 2>/dev/null; then + echo "Failed to change dir to $WORKING_DIR. Aborting..." +fi + +[[ -s "$GVM_ROOT/scripts/gvm" ]] && source "$GVM_ROOT/scripts/gvm" + +echo "Installing $GIT_TAG_UPGRADE_FROM $BINARY" +git clone $GIT_FAIRYRING_REPO $GIT_TAG_UPGRADE_FROM +cd "$WORKING_DIR/$GIT_TAG_UPGRADE_FROM" +git checkout $GIT_TAG_UPGRADE_FROM +echo "Building the 'Upgrade From' $BINARY" +gvm use $GO_VERSION_FROM +go mod tidy +make build + +echo "Installing $GIT_TAG_UPGRADE_TO $BINARY" +cd "$WORKING_DIR" +git clone $GIT_FAIRYRING_REPO $GIT_TAG_UPGRADE_TO cd "$WORKING_DIR/$GIT_TAG_UPGRADE_TO" echo $GIT_TAG_UPGRADE_TO -#git checkout $GIT_TAG_UPGRADE_TO +git checkout $GIT_TAG_UPGRADE_TO echo "Building the 'Upgrade To' $BINARY" gvm use $GO_VERSION_TO go mod tidy @@ -74,7 +77,9 @@ $BINARY_FULL_PATH init test --chain-id $CHAIN_ID --home $CHAIN_HOME --overwrite cat <<< $(jq '.app_state.gov.params.voting_period = "20s"' $CHAIN_HOME/config/genesis.json) > $CHAIN_HOME/config/genesis.json cat <<< $(jq '.app_state.gov.params.expedited_voting_period = "10s"' $CHAIN_HOME/config/genesis.json) > $CHAIN_HOME/config/genesis.json -$BINARY_FULL_PATH keys add validator --keyring-backend test --home $CHAIN_HOME +VAL_MNEMONIC_1="clock post desk civil pottery foster expand merit dash seminar song memory figure uniform spice circle try happy obvious trash crime hybrid hood cushion" + +echo $VAL_MNEMONIC_1 | $BINARY_FULL_PATH keys add validator --keyring-backend test --home $CHAIN_HOME --recover $BINARY_FULL_PATH keys add wallet1 --keyring-backend test --home $CHAIN_HOME $BINARY_FULL_PATH genesis add-genesis-account validator 100000000000ufairy,10000000000000stake --keyring-backend test --home $CHAIN_HOME $BINARY_FULL_PATH genesis add-genesis-account wallet1 100000000000ufairy,10000000000000stake --keyring-backend test --home $CHAIN_HOME @@ -128,25 +133,25 @@ echo $UPGRADE_PROPOSAL > upgrade_proposal.json echo "Setting up the chain upgrade..." $UPGRADER add-upgrade $UPGRADE_NAME $WORKING_DIR/$GIT_TAG_UPGRADE_TO/build/$BINARY -sleep 10 +sleep $(($BLOCK_TIME * 2)) $BINARY_FULL_PATH tx gov submit-proposal upgrade_proposal.json --from validator --chain-id $CHAIN_ID --keyring-backend test --home $CHAIN_HOME --yes -sleep 5 +sleep $BLOCK_TIME $BINARY_FULL_PATH tx gov vote 1 yes --from validator --yes --keyring-backend test --chain-id $CHAIN_ID --home $CHAIN_HOME -sleep 5 +sleep $BLOCK_TIME VAL_OP_ADDR=$($BINARY_FULL_PATH q staking validators -o json | jq -r '.validators[0].operator_address') OUT=$($BINARY_FULL_PATH tx staking delegate $VAL_OP_ADDR 10stake --from wallet1 --chain-id $CHAIN_ID --keyring-backend test --home $CHAIN_HOME --yes -o json) echo "Sent Delegate Tx: Code: $(echo $OUT | jq -r '.code'), Logs: $(echo $OUT | jq -r '.raw_log'), Hash: $(echo $OUT | jq -r '.txhash')" -sleep 5 +sleep $BLOCK_TIME VAL_ADDR=$($BINARY_FULL_PATH keys show validator --keyring-backend test --home $CHAIN_HOME -a) WAL1_ADDR=$($BINARY_FULL_PATH keys show wallet1 --keyring-backend test --home $CHAIN_HOME -a) OUT=$($BINARY_FULL_PATH tx bank send $WAL1_ADDR $VAL_ADDR 1stake --from wallet1 --chain-id $CHAIN_ID --keyring-backend test --home $CHAIN_HOME --yes -o json) echo "Sent Bank Send Tx: Code: $(echo $OUT | jq -r '.code'), Logs: $(echo $OUT | jq -r '.raw_log'), Hash: $(echo $OUT | jq -r '.txhash')" -sleep 6 +sleep $BLOCK_TIME echo "Sequence after tx: $($BINARY_FULL_PATH q auth account $WAL1_ADDR -o json | jq -r '.account.value.sequence'), Balance after tx: $($BINARY_FULL_PATH q bank balances $VAL_ADDR -o json | jq -r '.balances[0]')" echo "Waiting chain to upgrade..." @@ -156,27 +161,25 @@ echo "Sequence after upgrade: $($BINARY_FULL_PATH q auth account $WAL1_ADDR -o j OUT=$($BINARY_FULL_PATH tx bank send $WAL1_ADDR $VAL_ADDR 1stake --from wallet1 --chain-id $CHAIN_ID --keyring-backend test --home $CHAIN_HOME --yes -o json) echo "Sent Bank Send Tx After UPGRADE: Code: $(echo $OUT | jq -r '.code'), Logs: $(echo $OUT | jq -r '.raw_log'), Hash: $(echo $OUT | jq -r '.txhash')" -sleep 6 +sleep $BLOCK_TIME echo "Sequence after tx: $($BINARY_FULL_PATH q auth account $WAL1_ADDR -o json | jq -r '.account.value.sequence'), Balance after tx: $($BINARY_FULL_PATH q bank balances $VAL_ADDR -o json | jq -r '.balances[0]')" OUT=$($BINARY_FULL_PATH tx staking delegate $VAL_OP_ADDR 10stake --from wallet1 --chain-id $CHAIN_ID --keyring-backend test --home $CHAIN_HOME --yes -o json) echo "Sent Delegate Tx: Code: $(echo $OUT | jq -r '.code'), Logs: $(echo $OUT | jq -r '.raw_log'), Hash: $(echo $OUT | jq -r '.txhash')" -sleep 5 +sleep $BLOCK_TIME VAL_ADDR=$($BINARY_FULL_PATH keys show validator --keyring-backend test --home $CHAIN_HOME -a) WAL1_ADDR=$($BINARY_FULL_PATH keys show wallet1 --keyring-backend test --home $CHAIN_HOME -a) OUT=$($BINARY_FULL_PATH tx bank send $WAL1_ADDR $VAL_ADDR 1stake --from wallet1 --chain-id $CHAIN_ID --keyring-backend test --home $CHAIN_HOME --yes -o json) echo "Sent Bank Send Tx: Code: $(echo $OUT | jq -r '.code'), Logs: $(echo $OUT | jq -r '.raw_log'), Hash: $(echo $OUT | jq -r '.txhash')" -sleep 6 +sleep $BLOCK_TIME echo "Sequence after tx: $($BINARY_FULL_PATH q auth account $WAL1_ADDR -o json | jq -r '.account.value.sequence'), Balance after tx: $($BINARY_FULL_PATH q bank balances $VAL_ADDR -o json | jq -r '.balances[0]')" - -BINARY=$BINARY_FULL_PATH +BINARY=$NEW_BINARY_FULL_PATH CHAINID_1=$CHAIN_ID -BLOCK_TIME=6 WALLET_1=$($BINARY keys show wallet1 -a --keyring-backend test --home $CHAIN_HOME) VALIDATOR_1=$($BINARY keys show validator -a --keyring-backend test --home $CHAIN_HOME) @@ -189,6 +192,15 @@ check_tx_code () { fi } +check_tx_err () { + local TX_CODE=$(echo "$1" | jq -r '.code') + if [ "$TX_CODE" -eq 0 ]; then + return 0 + else + return 1 + fi +} + wait_for_tx () { sleep $BLOCK_TIME local TXHASH=$(echo "$1" | jq -r '.txhash') @@ -196,6 +208,10 @@ wait_for_tx () { echo "$RESULT" } +echo "###########################" +echo "# Testing Keyshare Module #" +echo "###########################" + echo "Staked account registering as a validator on chain $CHAINID_1" RESULT=$($BINARY tx keyshare register-validator --from $VALIDATOR_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --broadcast-mode sync --keyring-backend test -o json -y) @@ -224,6 +240,8 @@ if [ "$VALIDATOR_ADDR" != "$VALIDATOR_1" ]; then exit 1 fi +sleep 2 + CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_HOME -o json | jq -r '.block.header.height') TARGET_HEIGHT=$((CURRENT_BLOCK+1)) EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $TARGET_HEIGHT) @@ -241,8 +259,9 @@ if [ "$AGGRED_SHARE" != $EXTRACTED_SHARE ]; then exit 1 fi -./scripts/tests/keyshareSender.sh $BINARY $CHAIN_HOME tcp://localhost:26657 $VALIDATOR_1 $CHAINID_1 > $WORKING_DIR/keyshareSender.log 2>&1 & - +echo $(pwd) +echo $CURRENT_PATH +$CURRENT_PATH/scripts/tests/keyshareSender.sh $BINARY $CHAIN_HOME tcp://localhost:26657 $VALIDATOR_1 $CHAINID_1 > $WORKING_DIR/keyshareSender.log 2>&1 & echo "Query submitted key share on chain $CHAINID_1" RESULT=$($BINARY query keyshare list-key-share -o json) @@ -268,7 +287,9 @@ exit 1 fi echo "Key Share Successfully aggregated: '$RESULT_DATA'" -# PEP +echo "######################" +echo "# Testing PEP Module #" +echo "######################" echo "Query account pep nonce before submitting encrypted tx from pep module on chain $CHAINID_1" RESULT=$($BINARY query pep show-pep-nonce $VALIDATOR_1 --home $CHAIN_HOME --chain-id $CHAINID_1 -o json) @@ -295,9 +316,9 @@ $BINARY tx bank send $VALIDATOR_1 $WALLET_1 1$TARGET_BAL_DENOM --from $VALIDATOR SIGNED_DATA=$($BINARY tx sign unsigned.json --from $VALIDATOR_1 --offline --account-number 0 --sequence $VALIDATOR_PEP_NONCE_BEFORE --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --keyring-backend test -y) CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_HOME -o json | jq -r '.block.header.height') -TARGET_BLOCK=$(($CURRENT_BLOCK+5)) +TARGET_BLOCK=$(($CURRENT_BLOCK+3)) echo "Encrypting signed tx with Pub key: '$PUB_KEY'" -CIPHER=$($BINARY encrypt $TARGET_BLOCK "" $SIGNED_DATA --node $CHAIN1_NODE) +CIPHER=$($BINARY encrypt $TARGET_BLOCK "" $SIGNED_DATA --node tcp://localhost:26657) rm -r unsigned.json &> /dev/null @@ -326,13 +347,14 @@ BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') BAL_AMT=$(echo "$RESULT" | jq -r '.balances[0].amount') echo "Balance after submitting first encrypted tx: $BAL_AMT$BAL_DENOM" +sleep $(($BLOCK_TIME * 5)) echo "Query target account token balance after encrypted tx being executed from pep module on chain $CHAINID_1" RESULT=$($BINARY query bank balances $WALLET_1 -o json) TARGET_BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') TARGET_BAL_AFTER=$(echo "$RESULT" | jq -r '.balances[0].amount') echo "Target account has: $TARGET_BAL_AFTER $TARGET_BAL_DENOM after encrypted bank send tx being executed, balance increased $(($TARGET_BAL_AFTER - $TARGET_BAL)) $TARGET_BAL_DENOM" -if [ "$TARGET_BAL_AFTER" == "$TARGET_BAL" ]; then +if [[ "$TARGET_BAL_AFTER" -eq "$TARGET_BAL" ]]; then echo "ERROR: Pep module encrypted tx execution error. Expected Target Balance to be updated, got same balance: '$TARGET_BAL_AFTER $TARGET_BAL_DENOM'" exit 1 fi @@ -342,4 +364,90 @@ BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') BAL_AMT=$(echo "$RESULT" | jq -r '.balances[0].amount') echo "Balance after encrypted tx execution: $BAL_AMT$BAL_DENOM" -echo "Run 'pkill fairyringd' later to stop fairyring" \ No newline at end of file + +echo "############################" +echo "# Testing General Keyshare #" +echo "############################" + +echo "Creating new General Enc Request in pep module on chain $CHAIN_ID" +RESULT=$($BINARY tx pep request-general-keyshare 30s testing123 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT + +sleep $(($BLOCK_TIME * 2)) + +echo "Query general keyshare request on chain $CHAIN_ID" +LIST_KEYSHARE_REQ=$($BINARY query pep list-keyshare-req -o json) +IDENTITY=$(echo $LIST_KEYSHARE_REQ | jq -r '.keyshares[0].identity') +REQ_ID=$(echo $LIST_KEYSHARE_REQ | jq -r '.keyshares[0].request_id') +echo "Identity for keyshare request 1 is: $IDENTITY" + + +echo "Query account pep nonce before submitting encrypted tx from pep module on chain $CHAIN_ID" +RESULT=$($BINARY query pep show-pep-nonce $WALLET_1 --home $CHAIN_HOME --chain-id $CHAINID_1 -o json) +PEP_NONCE_BEFORE=$(echo "$RESULT" | jq -r '.pepNonce.nonce') + +echo "Query target account token balance before submitting encrypted tx from pep module on chain $CHAIN_ID" +RESULT=$($BINARY query bank balances $VALIDATOR_1 -o json) +TARGET_BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') +TARGET_BAL=$(echo "$RESULT" | jq -r '.balances[0].amount') +echo "Target account has: $TARGET_BAL $TARGET_BAL_DENOM before encrypted bank send tx" + + +echo "Signing bank send tx with pep nonce: '$PEP_NONCE_BEFORE'" +echo "Sending 1 $TARGET_BAL_DENOM to target address" +$BINARY tx bank send $WALLET_1 $VALIDATOR_1 1$TARGET_BAL_DENOM --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --keyring-backend test --generate-only -o json -y > unsigned.json +SIGNED_DATA=$($BINARY tx sign unsigned.json --from $WALLET_1 --offline --account-number 1 --sequence $PEP_NONCE_BEFORE --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --keyring-backend test -y) + +echo "Encrypting signed tx with Pub key: '$PUB_KEY'" +CIPHER=$($BINARY encrypt $IDENTITY "" $SIGNED_DATA --node tcp://localhost:26657) + +rm -r unsigned.json &> /dev/null + +echo "Submit general encrypted tx to pep module on chain $CHAIN_ID" +RESULT=$($BINARY tx pep submit-general-encrypted-tx $CIPHER $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_HOME --chain-id $CHAINID_1 --broadcast-mode sync --keyring-backend test -o json -y) +echo "$RESULT" +check_tx_code $RESULT + +sleep $BLOCK_TIME + +echo "Query Keyshare request and check for encrypted tx" +TX=$($BINARY query pep show-keyshare-req $REQ_ID -o json | jq -r '.keyshare.tx_list.encryptedTx[0].data') +if [ "$TX" != "$CIPHER" ]; then + echo "Submitting general encrypted tx failed. Expected: $CIPHER, got $TX" + exit 1 +fi + +sleep $BLOCK_TIME + +echo "Request Generation of Aggr keyshare" +RESULT=$($BINARY tx pep get-general-keyshare $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_HOME --chain-id $CHAINID_1 --broadcast-mode sync --keyring-backend test -o json -y) +echo "$RESULT" +check_tx_code $RESULT + +sleep $BLOCK_TIME + +EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $IDENTITY) +EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') + +while true; do + echo "Submitting General Key Share" + + RESULT=$($BINARY tx keyshare create-general-key-share "private-gov-identity" $IDENTITY $EXTRACTED_SHARE 1 --from $VALIDATOR_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_HOME --chain-id $CHAINID_1 --broadcast-mode sync --keyring-backend test -o json -y) + echo "$RESULT" + check_tx_err $RESULT + if [ $? -eq 0 ]; then + break + fi +done + +sleep 15 + +echo "Query target account token balance after general encrypted tx being executed from pep module on chain $CHAIN_ID" +RESULT=$($BINARY query bank balances $VALIDATOR_1 -o json) +TARGET_BAL_DENOM=$(echo "$RESULT" | jq -r '.balances[0].denom') +TARGET_BAL_AFTER=$(echo "$RESULT" | jq -r '.balances[0].amount') +echo "Target account has: $TARGET_BAL_AFTER $TARGET_BAL_DENOM after encrypted bank send tx being executed, balance increased $(($TARGET_BAL_AFTER - $TARGET_BAL)) $TARGET_BAL_DENOM" +if [[ "$TARGET_BAL_AFTER" == "$TARGET_BAL" ]]; then + echo "ERROR: Pep module encrypted tx execution error. Expected Target Balance to be updated, got same balance: '$TARGET_BAL_AFTER $TARGET_BAL_DENOM'" + exit 1 +fi From a0e16ef1c1f4a1a368283f03241e2ef29cf7b8d7 Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Wed, 25 Sep 2024 21:40:17 -0400 Subject: [PATCH 10/41] Fix build error --- x/keyshare/module/module.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/x/keyshare/module/module.go b/x/keyshare/module/module.go index 10c01465..f08d5eb1 100644 --- a/x/keyshare/module/module.go +++ b/x/keyshare/module/module.go @@ -139,9 +139,6 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil { panic(fmt.Errorf("failed to migrate x/%s from version 1 to 2: %w", types.ModuleName, err)) } - if err := cfg.RegisterMigration(types.ModuleName, 2, m.Migrate2to3); err != nil { - panic(fmt.Errorf("failed to migrate x/%s from version 2 to 3: %w", types.ModuleName, err)) - } } // RegisterInvariants registers the invariants of the module. If an invariant deviates from its predicted value, the InvariantRegistry triggers appropriate logic (most often the chain will be halted) From a7b581fd3b44b3733df7c2f21553afa0085e5a95 Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Thu, 26 Sep 2024 18:43:18 +0530 Subject: [PATCH 11/41] adding test contract --- .gitignore | 3 +- fairyring_contract/Cargo.lock | 691 +++++++++++++++++++++ fairyring_contract/Cargo.toml | 15 + fairyring_contract/optimized_contract.wasm | Bin 0 -> 1342772 bytes fairyring_contract/src/contract.rs | 67 ++ fairyring_contract/src/error.rs | 0 fairyring_contract/src/lib.rs | 4 + fairyring_contract/src/msg.rs | 24 + fairyring_contract/src/state.rs | 4 + x/pep/keeper/contract.go | 6 +- 10 files changed, 812 insertions(+), 2 deletions(-) create mode 100644 fairyring_contract/Cargo.lock create mode 100644 fairyring_contract/Cargo.toml create mode 100644 fairyring_contract/optimized_contract.wasm create mode 100644 fairyring_contract/src/contract.rs create mode 100644 fairyring_contract/src/error.rs create mode 100644 fairyring_contract/src/lib.rs create mode 100644 fairyring_contract/src/msg.rs create mode 100644 fairyring_contract/src/state.rs diff --git a/.gitignore b/.gitignore index 01fd764c..f625d68e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ build/ DistributedIBE/ data/ devnet_data/ -github.com/ \ No newline at end of file +github.com/ +fairyring_contract/target/ \ No newline at end of file diff --git a/fairyring_contract/Cargo.lock b/fairyring_contract/Cargo.lock new file mode 100644 index 00000000..40bebcd1 --- /dev/null +++ b/fairyring_contract/Cargo.lock @@ -0,0 +1,691 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bnum" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cosmwasm-crypto" +version = "1.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58535cbcd599b3c193e3967c8292fe1dbbb5de7c2a2d87380661091dd4744044" +dependencies = [ + "digest 0.10.7", + "ed25519-zebra", + "k256", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "1.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e07de16c800ac82fd188d055ecdb923ead0cf33960d3350089260bb982c09f" +dependencies = [ + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-std" +version = "1.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c21fde95ccd20044a23c0ac6fd8c941f3e8c158169dc94b5aa6491a2d9551a8d" +dependencies = [ + "base64", + "bech32", + "bnum", + "cosmwasm-crypto", + "cosmwasm-derive", + "derivative", + "forward_ref", + "hex", + "schemars", + "serde", + "serde-json-wasm", + "sha2 0.10.8", + "static_assertions", + "thiserror", +] + +[[package]] +name = "cosmwasm-storage" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66de2ab9db04757bcedef2b5984fbe536903ada4a8a9766717a4a71197ef34f6" +dependencies = [ + "cosmwasm-std", + "serde", +] + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "cw-storage-plus" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d7ee1963302b0ac2a9d42fe0faec826209c17452bfd36fbfd9d002a88929261" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek", + "hashbrown", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "fairyring_contract" +version = "0.1.0" +dependencies = [ + "cosmwasm-std", + "cosmwasm-storage", + "cw-storage-plus", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2 0.10.8", + "signature", +] + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.77", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-json-wasm" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/fairyring_contract/Cargo.toml b/fairyring_contract/Cargo.toml new file mode 100644 index 00000000..20189009 --- /dev/null +++ b/fairyring_contract/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "fairyring_contract" +version = "0.1.0" +edition = "2018" + +[dependencies] +cosmwasm-std = "1.0" +cosmwasm-storage = "1.0" +cw-storage-plus = "0.11" +serde = { version = "1.0", features = ["derive"] } +schemars = "0.8" +thiserror = "1.0" + +[lib] +crate-type = ["cdylib", "rlib"] \ No newline at end of file diff --git a/fairyring_contract/optimized_contract.wasm b/fairyring_contract/optimized_contract.wasm new file mode 100644 index 0000000000000000000000000000000000000000..8f7eb2c675d75bef97be2a733017bb90735290a5 GIT binary patch literal 1342772 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�lC7w>A$7HfLA*S@b8$HZ;t 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

X$=W6JRxlbO2Uk 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ξ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�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

3lM|%X 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 StdResult { + // Store the data + + // Check if identity is a non-empty string + if msg.identity.trim().is_empty() { + return Err(StdError::generic_err("Identity cannot be empty")); + } + + // Use the identity directly + let identity = msg.identity; + + STORED_DATA.save( + deps.storage, + &identity, + &(msg.pubkey.clone(), msg.aggr_keyshare.clone()), // Use `.clone()` to avoid moving the values + )?; + + // Return a response + Ok(Response::new() + .add_attributes(vec![ + attr("action", "store_data"), + attr("identity", identity), + attr("pubkey", msg.pubkey), + attr("aggr_keyshare", msg.aggr_keyshare), + ]) + ) +} + + +#[entry_point] +pub fn query( + deps: Deps, + _env: Env, + msg: QueryMsg, +) -> StdResult { + // Load the stored data for the given identity + + // Check if identity is a non-empty string + if msg.identity.trim().is_empty() { + return Err(StdError::generic_err("Identity cannot be empty")); + } + + // Use the identity directly + let identity = msg.identity; + + let stored_data = STORED_DATA.load(deps.storage, &identity)?; + + // Create the response + let response = QueryResponse { + pubkey: stored_data.0, + aggr_keyshare: stored_data.1, + }; + + // Serialize the response to binary and return it + to_json_binary(&response) +} \ No newline at end of file diff --git a/fairyring_contract/src/error.rs b/fairyring_contract/src/error.rs new file mode 100644 index 00000000..e69de29b diff --git a/fairyring_contract/src/lib.rs b/fairyring_contract/src/lib.rs new file mode 100644 index 00000000..09b1e5f3 --- /dev/null +++ b/fairyring_contract/src/lib.rs @@ -0,0 +1,4 @@ +pub mod contract; +pub mod msg; +pub mod state; +pub mod error; \ No newline at end of file diff --git a/fairyring_contract/src/msg.rs b/fairyring_contract/src/msg.rs new file mode 100644 index 00000000..866cd0ca --- /dev/null +++ b/fairyring_contract/src/msg.rs @@ -0,0 +1,24 @@ +// msg.rs +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +// This is the message to execute the contract +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ExecuteContractMsg { + pub identity: String, + pub pubkey: String, + pub aggr_keyshare: String, +} + +// Query message +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct QueryMsg { + pub identity: String, +} + +// Response type for querying stored data +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct QueryResponse { + pub pubkey: String, + pub aggr_keyshare: String, +} diff --git a/fairyring_contract/src/state.rs b/fairyring_contract/src/state.rs new file mode 100644 index 00000000..893873ae --- /dev/null +++ b/fairyring_contract/src/state.rs @@ -0,0 +1,4 @@ +// state.rs +use cw_storage_plus::Map; + +pub const STORED_DATA: Map<&str, (String, String)> = Map::new("stored_data"); diff --git a/x/pep/keeper/contract.go b/x/pep/keeper/contract.go index 646f944c..a2c3b7e7 100644 --- a/x/pep/keeper/contract.go +++ b/x/pep/keeper/contract.go @@ -5,9 +5,11 @@ import ( "cosmossdk.io/store/prefix" storetypes "cosmossdk.io/store/types" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/Fairblock/fairyring/x/pep/types" "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) // SetContractEntry set a specific contract entry in the store by identity @@ -93,7 +95,9 @@ func (k Keeper) ExecuteContract(ctx sdk.Context, contractAddr string, msg types. k.logger.Error("error marshalling msg for contract: %s", contractAddr) return } - _, err = k.wasmKeeper.Execute(ctx, addr, addr, msgBytes, sdk.Coins{}) + + wasmAddr := authtypes.NewModuleAddress(wasmtypes.ModuleName) + _, err = k.wasmKeeper.Execute(ctx, addr, wasmAddr, msgBytes, sdk.Coins{}) if err != nil { k.logger.Error("error executing contract: %s", contractAddr) } From de554523427b9f8d3e07ffb479573d42b7dafdbc Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Fri, 27 Sep 2024 13:47:02 +0530 Subject: [PATCH 12/41] updating testscript and fixing minor issues --- api/fairyring/pep/query.pulsar.go | 304 ++++++++++----------- fairyring_contract/Cargo.lock | 62 +++++ fairyring_contract/Cargo.toml | 2 + fairyring_contract/optimized_contract.wasm | Bin 1342772 -> 1373285 bytes fairyring_contract/src/contract.rs | 88 +++++- fairyring_contract/src/lib.rs | 19 +- fairyring_contract/src/msg.rs | 27 +- go.mod | 2 +- go.sum | 2 - proto/fairyring/pep/query.proto | 6 +- scripts/tests/pep.sh | 64 +++++ scripts/tests/start.sh | 4 +- x/pep/client/cli/tx.go | 1 + x/pep/client/cli/tx_register_contract.go | 41 +++ x/pep/keeper/contract.go | 5 +- x/pep/module/autocli.go | 2 +- x/pep/types/msg_register_contract.go | 33 +++ x/pep/types/query.pb.go | 176 ++++++------ x/pep/types/query.pb.gw.go | 28 +- 19 files changed, 583 insertions(+), 283 deletions(-) create mode 100644 x/pep/client/cli/tx_register_contract.go create mode 100644 x/pep/types/msg_register_contract.go diff --git a/api/fairyring/pep/query.pulsar.go b/api/fairyring/pep/query.pulsar.go index 04b17f56..a15813bd 100644 --- a/api/fairyring/pep/query.pulsar.go +++ b/api/fairyring/pep/query.pulsar.go @@ -10006,18 +10006,18 @@ func (x *fastReflection_QueryShowPrivateKeyshareReqResponse) ProtoMethods() *pro } var ( - md_QueryDecryptDataRequest protoreflect.MessageDescriptor - fd_QueryDecryptDataRequest_pubkey protoreflect.FieldDescriptor - fd_QueryDecryptDataRequest_aggrKeyshare protoreflect.FieldDescriptor - fd_QueryDecryptDataRequest_encryptedData protoreflect.FieldDescriptor + md_QueryDecryptDataRequest protoreflect.MessageDescriptor + fd_QueryDecryptDataRequest_pubkey protoreflect.FieldDescriptor + fd_QueryDecryptDataRequest_aggr_keyshare protoreflect.FieldDescriptor + fd_QueryDecryptDataRequest_encrypted_data protoreflect.FieldDescriptor ) func init() { file_fairyring_pep_query_proto_init() md_QueryDecryptDataRequest = File_fairyring_pep_query_proto.Messages().ByName("QueryDecryptDataRequest") fd_QueryDecryptDataRequest_pubkey = md_QueryDecryptDataRequest.Fields().ByName("pubkey") - fd_QueryDecryptDataRequest_aggrKeyshare = md_QueryDecryptDataRequest.Fields().ByName("aggrKeyshare") - fd_QueryDecryptDataRequest_encryptedData = md_QueryDecryptDataRequest.Fields().ByName("encryptedData") + fd_QueryDecryptDataRequest_aggr_keyshare = md_QueryDecryptDataRequest.Fields().ByName("aggr_keyshare") + fd_QueryDecryptDataRequest_encrypted_data = md_QueryDecryptDataRequest.Fields().ByName("encrypted_data") } var _ protoreflect.Message = (*fastReflection_QueryDecryptDataRequest)(nil) @@ -10093,13 +10093,13 @@ func (x *fastReflection_QueryDecryptDataRequest) Range(f func(protoreflect.Field } if x.AggrKeyshare != "" { value := protoreflect.ValueOfString(x.AggrKeyshare) - if !f(fd_QueryDecryptDataRequest_aggrKeyshare, value) { + if !f(fd_QueryDecryptDataRequest_aggr_keyshare, value) { return } } if x.EncryptedData != "" { value := protoreflect.ValueOfString(x.EncryptedData) - if !f(fd_QueryDecryptDataRequest_encryptedData, value) { + if !f(fd_QueryDecryptDataRequest_encrypted_data, value) { return } } @@ -10120,9 +10120,9 @@ func (x *fastReflection_QueryDecryptDataRequest) Has(fd protoreflect.FieldDescri switch fd.FullName() { case "fairyring.pep.QueryDecryptDataRequest.pubkey": return x.Pubkey != "" - case "fairyring.pep.QueryDecryptDataRequest.aggrKeyshare": + case "fairyring.pep.QueryDecryptDataRequest.aggr_keyshare": return x.AggrKeyshare != "" - case "fairyring.pep.QueryDecryptDataRequest.encryptedData": + case "fairyring.pep.QueryDecryptDataRequest.encrypted_data": return x.EncryptedData != "" default: if fd.IsExtension() { @@ -10142,9 +10142,9 @@ func (x *fastReflection_QueryDecryptDataRequest) Clear(fd protoreflect.FieldDesc switch fd.FullName() { case "fairyring.pep.QueryDecryptDataRequest.pubkey": x.Pubkey = "" - case "fairyring.pep.QueryDecryptDataRequest.aggrKeyshare": + case "fairyring.pep.QueryDecryptDataRequest.aggr_keyshare": x.AggrKeyshare = "" - case "fairyring.pep.QueryDecryptDataRequest.encryptedData": + case "fairyring.pep.QueryDecryptDataRequest.encrypted_data": x.EncryptedData = "" default: if fd.IsExtension() { @@ -10165,10 +10165,10 @@ func (x *fastReflection_QueryDecryptDataRequest) Get(descriptor protoreflect.Fie case "fairyring.pep.QueryDecryptDataRequest.pubkey": value := x.Pubkey return protoreflect.ValueOfString(value) - case "fairyring.pep.QueryDecryptDataRequest.aggrKeyshare": + case "fairyring.pep.QueryDecryptDataRequest.aggr_keyshare": value := x.AggrKeyshare return protoreflect.ValueOfString(value) - case "fairyring.pep.QueryDecryptDataRequest.encryptedData": + case "fairyring.pep.QueryDecryptDataRequest.encrypted_data": value := x.EncryptedData return protoreflect.ValueOfString(value) default: @@ -10193,9 +10193,9 @@ func (x *fastReflection_QueryDecryptDataRequest) Set(fd protoreflect.FieldDescri switch fd.FullName() { case "fairyring.pep.QueryDecryptDataRequest.pubkey": x.Pubkey = value.Interface().(string) - case "fairyring.pep.QueryDecryptDataRequest.aggrKeyshare": + case "fairyring.pep.QueryDecryptDataRequest.aggr_keyshare": x.AggrKeyshare = value.Interface().(string) - case "fairyring.pep.QueryDecryptDataRequest.encryptedData": + case "fairyring.pep.QueryDecryptDataRequest.encrypted_data": x.EncryptedData = value.Interface().(string) default: if fd.IsExtension() { @@ -10219,10 +10219,10 @@ func (x *fastReflection_QueryDecryptDataRequest) Mutable(fd protoreflect.FieldDe switch fd.FullName() { case "fairyring.pep.QueryDecryptDataRequest.pubkey": panic(fmt.Errorf("field pubkey of message fairyring.pep.QueryDecryptDataRequest is not mutable")) - case "fairyring.pep.QueryDecryptDataRequest.aggrKeyshare": - panic(fmt.Errorf("field aggrKeyshare of message fairyring.pep.QueryDecryptDataRequest is not mutable")) - case "fairyring.pep.QueryDecryptDataRequest.encryptedData": - panic(fmt.Errorf("field encryptedData of message fairyring.pep.QueryDecryptDataRequest is not mutable")) + case "fairyring.pep.QueryDecryptDataRequest.aggr_keyshare": + panic(fmt.Errorf("field aggr_keyshare of message fairyring.pep.QueryDecryptDataRequest is not mutable")) + case "fairyring.pep.QueryDecryptDataRequest.encrypted_data": + panic(fmt.Errorf("field encrypted_data of message fairyring.pep.QueryDecryptDataRequest is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.QueryDecryptDataRequest")) @@ -10238,9 +10238,9 @@ func (x *fastReflection_QueryDecryptDataRequest) NewField(fd protoreflect.FieldD switch fd.FullName() { case "fairyring.pep.QueryDecryptDataRequest.pubkey": return protoreflect.ValueOfString("") - case "fairyring.pep.QueryDecryptDataRequest.aggrKeyshare": + case "fairyring.pep.QueryDecryptDataRequest.aggr_keyshare": return protoreflect.ValueOfString("") - case "fairyring.pep.QueryDecryptDataRequest.encryptedData": + case "fairyring.pep.QueryDecryptDataRequest.encrypted_data": return protoreflect.ValueOfString("") default: if fd.IsExtension() { @@ -11802,8 +11802,8 @@ type QueryDecryptDataRequest struct { unknownFields protoimpl.UnknownFields Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` - AggrKeyshare string `protobuf:"bytes,2,opt,name=aggrKeyshare,proto3" json:"aggrKeyshare,omitempty"` - EncryptedData string `protobuf:"bytes,3,opt,name=encryptedData,proto3" json:"encryptedData,omitempty"` + AggrKeyshare string `protobuf:"bytes,2,opt,name=aggr_keyshare,json=aggrKeyshare,proto3" json:"aggr_keyshare,omitempty"` + EncryptedData string `protobuf:"bytes,3,opt,name=encrypted_data,json=encryptedData,proto3" json:"encrypted_data,omitempty"` } func (x *QueryDecryptDataRequest) Reset() { @@ -12040,140 +12040,140 @@ var file_fairyring_pep_query_proto_rawDesc = []byte{ 0x0b, 0x32, 0x23, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x12, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, - 0x64, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x22, 0x7b, 0x0a, 0x17, 0x51, 0x75, + 0x64, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x22, 0x7d, 0x0a, 0x17, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x22, 0x0a, - 0x0c, 0x61, 0x67, 0x67, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x67, 0x67, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, - 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x22, 0x41, 0x0a, 0x18, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, - 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x32, 0xec, 0x0d, 0x0a, 0x05, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x12, 0x6e, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x21, - 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x22, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, - 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, - 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x70, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x12, 0xa0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x65, 0x64, 0x54, 0x78, 0x12, 0x29, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, - 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, - 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x34, 0x12, 0x32, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, - 0x70, 0x65, 0x70, 0x2f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x78, - 0x2f, 0x7b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x7d, 0x2f, - 0x7b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x7d, 0x12, 0x8c, 0x01, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x41, 0x6c, 0x6c, 0x12, 0x29, 0x2e, 0x66, 0x61, 0x69, - 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, 0x0a, + 0x0d, 0x61, 0x67, 0x67, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x67, 0x67, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, + 0x72, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x22, 0x41, 0x0a, 0x18, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, + 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, + 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x32, 0xee, 0x0d, 0x0a, + 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x6e, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x12, 0x21, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, + 0x15, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, + 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0xa0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x12, 0x29, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, + 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x45, + 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, + 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x12, 0x32, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, + 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, + 0x74, 0x78, 0x2f, 0x7b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x7d, 0x2f, 0x7b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x7d, 0x12, 0x8c, 0x01, 0x0a, 0x0e, 0x45, 0x6e, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x41, 0x6c, 0x6c, 0x12, 0x29, 0x2e, 0x66, + 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, + 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, + 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x66, 0x61, + 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x65, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x78, 0x12, 0xb9, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x41, 0x6c, 0x6c, 0x46, 0x72, 0x6f, 0x6d, 0x48, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x33, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x6e, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x65, 0x64, 0x5f, 0x74, 0x78, 0x12, 0xb9, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x41, 0x6c, 0x6c, 0x46, 0x72, 0x6f, 0x6d, 0x48, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x12, 0x33, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x46, 0x72, 0x6f, 0x6d, 0x48, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x46, 0x72, 0x6f, 0x6d, 0x48, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x66, 0x61, 0x69, + 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x46, 0x72, + 0x6f, 0x6d, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x12, 0x2a, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, + 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, + 0x65, 0x64, 0x5f, 0x74, 0x78, 0x2f, 0x7b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x7d, 0x12, 0x87, 0x01, 0x0a, 0x0c, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x48, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x27, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, + 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x61, 0x74, 0x65, 0x73, + 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, + 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, + 0x12, 0x1c, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, + 0x2f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x87, + 0x01, 0x0a, 0x08, 0x50, 0x65, 0x70, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x66, 0x61, + 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x47, 0x65, 0x74, 0x50, 0x65, 0x70, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x50, 0x65, 0x70, 0x4e, + 0x6f, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x70, 0x65, 0x70, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x2f, 0x7b, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x0b, 0x50, 0x65, 0x70, + 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x41, 0x6c, 0x6c, 0x12, 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, - 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x46, 0x72, 0x6f, 0x6d, - 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x12, 0x2a, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, - 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, - 0x5f, 0x74, 0x78, 0x2f, 0x7b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x7d, 0x12, 0x87, 0x01, 0x0a, 0x0c, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x48, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x12, 0x27, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x48, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x66, + 0x6c, 0x50, 0x65, 0x70, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x27, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x70, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1a, 0x12, 0x18, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, + 0x70, 0x2f, 0x70, 0x65, 0x70, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x6f, 0x0a, 0x06, 0x50, + 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, + 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, + 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x75, + 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x12, 0x82, 0x01, 0x0a, + 0x0b, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x12, 0x23, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, - 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x6c, - 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x87, 0x01, 0x0a, - 0x08, 0x50, 0x65, 0x70, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, - 0x65, 0x74, 0x50, 0x65, 0x70, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, - 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x50, 0x65, 0x70, 0x4e, 0x6f, 0x6e, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x24, 0x12, 0x22, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, - 0x65, 0x70, 0x2f, 0x70, 0x65, 0x70, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x2f, 0x7b, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x0b, 0x50, 0x65, 0x70, 0x4e, 0x6f, - 0x6e, 0x63, 0x65, 0x41, 0x6c, 0x6c, 0x12, 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, - 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, - 0x65, 0x70, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, - 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x70, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, - 0x18, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, - 0x70, 0x65, 0x70, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x6f, 0x0a, 0x06, 0x50, 0x75, 0x62, - 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, - 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x75, 0x62, 0x4b, - 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x18, 0x12, 0x16, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, - 0x65, 0x70, 0x2f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x12, 0x82, 0x01, 0x0a, 0x0b, 0x4b, - 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x12, 0x23, 0x2e, 0x66, 0x61, 0x69, - 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x24, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, + 0x72, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x24, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, + 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, + 0x20, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, + 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x5f, 0x69, 0x64, + 0x7d, 0x12, 0x82, 0x01, 0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, + 0x71, 0x41, 0x6c, 0x6c, 0x12, 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, + 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, + 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x6b, 0x65, - 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x5f, 0x69, 0x64, 0x7d, 0x12, - 0x82, 0x01, 0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x41, - 0x6c, 0x6c, 0x12, 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, - 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, - 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x61, 0x69, - 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x66, 0x61, - 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x6b, 0x65, 0x79, 0x73, - 0x68, 0x61, 0x72, 0x65, 0x12, 0xc3, 0x01, 0x0a, 0x16, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x72, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x12, - 0x31, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, - 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x72, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, 0x12, 0x3a, - 0x2f, 0x46, 0x61, 0x69, 0x72, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, - 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x70, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x5f, 0x72, - 0x65, 0x71, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x49, 0x64, 0x7d, 0x12, 0xac, 0x01, 0x0a, 0x0b, 0x44, - 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x26, 0x2e, 0x66, 0x61, 0x69, - 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, - 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, - 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4c, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x46, 0x12, 0x44, 0x2f, 0x46, 0x61, 0x69, 0x72, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, - 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x64, 0x65, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x7b, 0x61, 0x67, 0x67, 0x72, - 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x7d, 0x2f, 0x7b, 0x65, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x7d, 0x42, 0x94, 0x01, 0x0a, 0x11, 0x63, 0x6f, - 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x42, - 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0xa2, 0x02, 0x03, - 0x46, 0x50, 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x50, 0x65, 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, - 0x50, 0x65, 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, - 0x50, 0x65, 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x0e, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x50, 0x65, 0x70, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0xc3, 0x01, 0x0a, 0x16, 0x53, 0x68, 0x6f, 0x77, 0x50, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, + 0x71, 0x12, 0x31, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, + 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, + 0x12, 0x3a, 0x2f, 0x46, 0x61, 0x69, 0x72, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, 0x66, 0x61, 0x69, + 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x5f, + 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, + 0x5f, 0x72, 0x65, 0x71, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x49, 0x64, 0x7d, 0x12, 0xae, 0x01, 0x0a, + 0x0b, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x26, 0x2e, 0x66, + 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4e, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x12, 0x46, 0x2f, 0x46, 0x61, 0x69, 0x72, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, + 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x7b, 0x61, 0x67, + 0x67, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x7d, 0x2f, 0x7b, 0x65, 0x6e, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x7d, 0x42, 0x94, 0x01, + 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x70, 0x65, 0x70, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, + 0x70, 0xa2, 0x02, 0x03, 0x46, 0x50, 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, + 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, + 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, + 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x3a, 0x50, 0x65, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/fairyring_contract/Cargo.lock b/fairyring_contract/Cargo.lock index 40bebcd1..3a73b6a7 100644 --- a/fairyring_contract/Cargo.lock +++ b/fairyring_contract/Cargo.lock @@ -13,6 +13,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + [[package]] name = "base16ct" version = "0.2.0" @@ -67,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + [[package]] name = "cfg-if" version = "1.0.0" @@ -265,6 +277,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -291,6 +309,8 @@ dependencies = [ "cosmwasm-std", "cosmwasm-storage", "cw-storage-plus", + "prost", + "prost-types", "schemars", "serde", "thiserror", @@ -369,6 +389,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -432,6 +461,39 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b" +dependencies = [ + "bytes", + "prost", +] + [[package]] name = "quote" version = "1.0.37" diff --git a/fairyring_contract/Cargo.toml b/fairyring_contract/Cargo.toml index 20189009..f13ef082 100644 --- a/fairyring_contract/Cargo.toml +++ b/fairyring_contract/Cargo.toml @@ -10,6 +10,8 @@ cw-storage-plus = "0.11" serde = { version = "1.0", features = ["derive"] } schemars = "0.8" thiserror = "1.0" +prost = "0.8" # Protobuf support +prost-types = "0.8" [lib] crate-type = ["cdylib", "rlib"] \ No newline at end of file diff --git a/fairyring_contract/optimized_contract.wasm b/fairyring_contract/optimized_contract.wasm index 8f7eb2c675d75bef97be2a733017bb90735290a5..1ae2ad0706683740caeea44f2acfecd45110398a 100644 GIT binary patch delta 91814 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 delta 63254 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 Ks|rH*KK;KxC)>XO diff --git a/fairyring_contract/src/contract.rs b/fairyring_contract/src/contract.rs index f1afc2f2..66cf52f8 100644 --- a/fairyring_contract/src/contract.rs +++ b/fairyring_contract/src/contract.rs @@ -1,6 +1,7 @@ // contract.rs -use cosmwasm_std::{attr, entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; -use crate::msg::{ExecuteContractMsg, QueryMsg, QueryResponse}; +use cosmwasm_std::{attr, entry_point, to_json_binary, Binary, QueryRequest, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; +use prost::Message; +use crate::msg::{ExecuteContractMsg, QueryMsg, QueryResponse, InstantiateMsg, QueryDecryptDataResponse}; use crate::state::STORED_DATA; #[entry_point] @@ -40,28 +41,85 @@ pub fn execute( #[entry_point] pub fn query( - deps: Deps, + deps: Deps, _env: Env, msg: QueryMsg, ) -> StdResult { - // Load the stored data for the given identity + match msg { + QueryMsg::GetStoredData { identity } => { + if identity.trim().is_empty() { + return Err(StdError::generic_err("Identity cannot be empty")); + } + let stored_data = STORED_DATA.load(deps.storage, &identity)?; + let response = QueryResponse { + pubkey: stored_data.0, + aggr_keyshare: stored_data.1, + }; + to_json_binary(&response) + } - // Check if identity is a non-empty string + QueryMsg::DecryptData { + pubkey, + aggr_keyshare, + encrypted_data, + } => { + if encrypted_data.trim().is_empty() || aggr_keyshare.trim().is_empty() { + return Err(StdError::generic_err("Invalid input data")); + } + + // Call the function to query the `pep` module + let response = query_pep_decrypt(deps, pubkey, aggr_keyshare, encrypted_data)?; + + // Return the decrypted data in binary format + to_json_binary(&response) + } + } +} + +#[entry_point] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> StdResult { + // Add logic to initialize the contract state here + + // For example, store some initial data if msg.identity.trim().is_empty() { return Err(StdError::generic_err("Identity cannot be empty")); } - // Use the identity directly - let identity = msg.identity; + STORED_DATA.save( + deps.storage, + &msg.identity, + &(msg.pubkey.clone(), msg.aggr_keyshare.clone()), + )?; + + Ok(Response::new().add_attribute("method", "instantiate")) +} + + +// Function to query the `DecryptData` RPC from your `pep` module +pub fn query_pep_decrypt( + deps: Deps, + pubkey : String, + aggr_keyshare: String, + encrypted_data: String, +) -> StdResult { + // Create the custom query + let request = QueryRequest::Custom(QueryMsg::DecryptData { + pubkey, + aggr_keyshare, + encrypted_data, + }); - let stored_data = STORED_DATA.load(deps.storage, &identity)?; + // Send the query + let raw_response: Binary = deps.querier.query(&request)?; - // Create the response - let response = QueryResponse { - pubkey: stored_data.0, - aggr_keyshare: stored_data.1, - }; + // Deserialize the protobuf response + let query_response = QueryDecryptDataResponse::decode(&*raw_response.0) + .map_err(|_| StdError::generic_err("Failed to decode protobuf response"))?; - // Serialize the response to binary and return it - to_json_binary(&response) + Ok(query_response.decrypted_data) } \ No newline at end of file diff --git a/fairyring_contract/src/lib.rs b/fairyring_contract/src/lib.rs index 09b1e5f3..822c445f 100644 --- a/fairyring_contract/src/lib.rs +++ b/fairyring_contract/src/lib.rs @@ -1,4 +1,21 @@ pub mod contract; pub mod msg; pub mod state; -pub mod error; \ No newline at end of file +pub mod error; + +// use cosmwasm_std::{entry_point, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; + +// #[entry_point] +// pub fn instantiate(deps: DepsMut, env: Env, info: MessageInfo, msg: InstantiateMsg) -> StdResult { +// contract::instantiate(deps, env, info, msg) +// } + +// #[entry_point] +// pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult { +// contract::execute(deps, env, info, msg) +// } + +// #[entry_point] +// pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +// contract::query(deps, env, msg) +// } diff --git a/fairyring_contract/src/msg.rs b/fairyring_contract/src/msg.rs index 866cd0ca..5b6ca7b4 100644 --- a/fairyring_contract/src/msg.rs +++ b/fairyring_contract/src/msg.rs @@ -1,6 +1,7 @@ // msg.rs use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use cosmwasm_std::CustomQuery; // This is the message to execute the contract #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -12,13 +13,35 @@ pub struct ExecuteContractMsg { // Query message #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct QueryMsg { - pub identity: String, +#[serde(rename_all = "snake_case")] +pub enum QueryMsg { + GetStoredData { identity: String }, + DecryptData { + pubkey: String, + aggr_keyshare: String, + encrypted_data: String, + }, } +impl CustomQuery for QueryMsg{} + // Response type for querying stored data #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct QueryResponse { pub pubkey: String, pub aggr_keyshare: String, } + +#[derive(Clone, PartialEq, prost::Message)] +pub struct QueryDecryptDataResponse { + #[prost(string, tag = "1")] + pub decrypted_data: String, +} + +// Instantiate message +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct InstantiateMsg { + pub identity: String, + pub pubkey: String, + pub aggr_keyshare: String, +} diff --git a/go.mod b/go.mod index 30363b1d..2b22821f 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22.4 replace ( cosmossdk.io/api => github.com/Fairblock/cosmossdk-api v0.7.5 - github.com/CosmWasm/wasmd => github.com/Fairblock/wasmd v0.50.6-fairyring + github.com/CosmWasm/wasmd => ../wasmd github.com/cosmos/cosmos-sdk => github.com/Fairblock/cosmos-sdk v0.50.8-fairyring // fix upstream GHSA-h395-qcrw-5vmq vulnerability. github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 diff --git a/go.sum b/go.sum index 9ac3f2b8..9f40c5de 100644 --- a/go.sum +++ b/go.sum @@ -243,8 +243,6 @@ github.com/Fairblock/cosmos-sdk v0.50.8-fairyring h1:b/nFqDT2lHXtam2KdN0s9RLVsYH github.com/Fairblock/cosmos-sdk v0.50.8-fairyring/go.mod h1:ep1ZTLXL8h62Xi6l6lJdto/Xt8CYlP+GW9MudPCT05w= github.com/Fairblock/cosmossdk-api v0.7.5 h1:2NON/rKYquaTpISPn5sOZTP80a2moKg7YN+HI7wi5Wk= github.com/Fairblock/cosmossdk-api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= -github.com/Fairblock/wasmd v0.50.6-fairyring h1:P5bEeEQbyLew8dD/kXP1JSjBB6ersyhORcnuYQp3+nI= -github.com/Fairblock/wasmd v0.50.6-fairyring/go.mod h1:f0oj8Oy6bzleydH5ytWMqQD7DCp23b2VKkdsTVmiLrE= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= diff --git a/proto/fairyring/pep/query.proto b/proto/fairyring/pep/query.proto index e5278674..d60c1c49 100644 --- a/proto/fairyring/pep/query.proto +++ b/proto/fairyring/pep/query.proto @@ -82,7 +82,7 @@ service Query { // Queries a list of DecryptData items. rpc DecryptData (QueryDecryptDataRequest) returns (QueryDecryptDataResponse) { - option (google.api.http).get = "/Fairblock/fairyring/pep/decrypt_data/{aggrKeyshare}/{encryptedData}"; + option (google.api.http).get = "/Fairblock/fairyring/pep/decrypt_data/{aggr_keyshare}/{encrypted_data}"; } } @@ -182,8 +182,8 @@ message QueryShowPrivateKeyshareReqResponse { message QueryDecryptDataRequest { string pubkey = 1; - string aggrKeyshare = 2; - string encryptedData = 3; + string aggr_keyshare = 2; + string encrypted_data = 3; } message QueryDecryptDataResponse { diff --git a/scripts/tests/pep.sh b/scripts/tests/pep.sh index 2dfed876..580a3fa6 100755 --- a/scripts/tests/pep.sh +++ b/scripts/tests/pep.sh @@ -15,6 +15,7 @@ echo "" BINARY=fairyringd CHAIN_DIR=$(pwd)/data +CONTRACT_DIR=$(pwd)/fairyring_contract CHAINID_1=fairyring_test_1 CHAIN1_NODE=tcp://localhost:16657 CHAINID_2=fairyring_test_2 @@ -805,6 +806,69 @@ else exit 1 fi +echo "#############################################" +echo "# Testing contract callback on source chain #" +echo "#############################################" + +echo "Deploying smart contract on source chain" +RESULT=$($BINARY tx wasm store $CONTRACT_DIR/optimized_contract.wasm --from $WALLET_1 --gas 9000000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test --fees 9000000ufairy -o json -y) +check_tx_code $RESULT + +sleep 10 + +echo "Instantiating the contract" +RESULT=$($BINARY tx wasm instantiate 1 '{"identity": "init_identity", "pubkey": "init_pubkey", "aggr_keyshare": "init_keyshare"}' --admin $WALLET_1 --from $WALLET_1 --gas 9000000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test --fees 9000000ufairy --label test_contract_1 -o json -y) +check_tx_code $RESULT + +sleep 10 + +echo "Creating new General keyshare Request on chain fairyring_test_1" +RESULT=$($BINARY tx pep request-general-keyshare 30s contract123 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT + +sleep 10 + +REQ_ID="fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/contract123" +CONTRACT_ADDR="fairy14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9stsyf7v" + +echo "Registering contract with identity" +RESULT=$($BINARY tx pep register-contract $CONTRACT_ADDR $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT + +sleep 10 + +echo "Request Generation of Aggr keyshare" +RESULT=$($BINARY tx pep get-general-keyshare $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) +echo "$RESULT" +check_tx_code $RESULT + +sleep 6 + +EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $REQ_ID) +EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') + +while true; do + echo "Submitting General Key Share" + + RESULT=$($BINARY tx keyshare create-general-key-share "private-gov-identity" $REQ_ID $EXTRACTED_SHARE 1 --from $VALIDATOR_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node tcp://localhost:16657 --broadcast-mode sync --keyring-backend test -o json -y) + echo "$RESULT" + check_tx_err $RESULT + if [ $? -eq 0 ]; then + break + fi +done + +sleep 15 + +echo "Query Contract state" +RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"get_stored_data":{"identity": "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/contract123"}}' --node $CHAIN1_NODE -o json) +echo $RSP + +echo "#############################################" +echo "# Testing contract callback on source chain #" +echo "#############################################" + +RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"decrypt_data": {"pubkey": "a2a4472488440341db3252447af1c31e06fd32d7067e300ed60052fcdd131fd702bf901e1dd0122a312bb582a9a375a3", "aggr_keyshare": "a3b49bbffd655aa37e0b71a4d90862e1f70bdd0aab48587307ef74c2b3e12fd2ea42d88fc5f592e5caf83d33d7f93454196f32137817ceb5ecb41fbe48c3734bb11510febd6988302dd2c362deb3479b4946daa399fb149e63c0a5c45b48292d", "encrypted_data": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20646973744942450a686e4a7641376d5655797679397166465230447849417464374c3152586371484542687736306a316f325a446e567453626a4759374a4d2f5a524752654e536b0a574d6f56567966674d55546f363944502f4f624a6544424e6f47694b50746a6b316a523075464276536372326d766948543238524f6e473755647835683077510a6c734767656554424336786e7834626e496d737874410a2d2d2d20793668724135506e5233563568414a35646f732b574e325932334b72742b383946306d4d743138595a59490a43129dfd9ddbb210374314a96ab1b06260b4e1abf7d3fac77029043c8bdbe0a6efd2b73f95f75be0"}}' --node $CHAIN1_NODE -o json) echo $RSP echo "" diff --git a/scripts/tests/start.sh b/scripts/tests/start.sh index 3370a3d6..37606e31 100755 --- a/scripts/tests/start.sh +++ b/scripts/tests/start.sh @@ -153,11 +153,11 @@ echo "$modifiedJson2" | jq '.' > "$CHAIN_DIR/$CHAINID_2/config/genesis.json" echo "Starting $CHAINID_1 in $CHAIN_DIR..." echo "Creating log file at $CHAIN_DIR/$CHAINID_1.log" -$BINARY start --log_level info --home $CHAIN_DIR/$CHAINID_1 --pruning=nothing --grpc.address="0.0.0.0:$GRPCPORT_1" > $CHAIN_DIR/$CHAINID_1.log 2>&1 & +$BINARY start --log_format json --log_level info --home $CHAIN_DIR/$CHAINID_1 --pruning=nothing --grpc.address="0.0.0.0:$GRPCPORT_1" > $CHAIN_DIR/$CHAINID_1.log 2>&1 & echo "Starting $CHAINID_2 in $CHAIN_DIR..." echo "Creating log file at $CHAIN_DIR/$CHAINID_2.log" -$BINARY start --log_level info --home $CHAIN_DIR/$CHAINID_2 --pruning=nothing --grpc.address="0.0.0.0:$GRPCPORT_2" > $CHAIN_DIR/$CHAINID_2.log 2>&1 & +$BINARY start --log_format json --log_level info --home $CHAIN_DIR/$CHAINID_2 --pruning=nothing --grpc.address="0.0.0.0:$GRPCPORT_2" > $CHAIN_DIR/$CHAINID_2.log 2>&1 & echo "Checking if there is an existing keys for Hermes Relayer..." HKEY_1=$(hermes --config hermes_config.toml keys list --chain fairyring_test_1 | sed -n '/SUCCESS/d; s/.*(\([^)]*\)).*/\1/p') diff --git a/x/pep/client/cli/tx.go b/x/pep/client/cli/tx.go index 47dfd167..46a211e3 100644 --- a/x/pep/client/cli/tx.go +++ b/x/pep/client/cli/tx.go @@ -32,6 +32,7 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand(CmdSubmitGeneralEncryptedTx()) cmd.AddCommand(CmdRequestPrivateKeyshare()) cmd.AddCommand(CmdGetPrivateKeyshare()) + cmd.AddCommand(CmdRegisterContract()) // this line is used by starport scaffolding # 1 return cmd diff --git a/x/pep/client/cli/tx_register_contract.go b/x/pep/client/cli/tx_register_contract.go new file mode 100644 index 00000000..eeeedffd --- /dev/null +++ b/x/pep/client/cli/tx_register_contract.go @@ -0,0 +1,41 @@ +package cli + +import ( + "strconv" + + "github.com/Fairblock/fairyring/x/pep/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/spf13/cobra" +) + +var _ = strconv.Itoa(0) + +func CmdRegisterContract() *cobra.Command { + cmd := &cobra.Command{ + Use: "register-contract [contract-address] [identity]", + Short: "Broadcast message register-contract", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := types.NewMsgRegisterContract( + clientCtx.GetFromAddress().String(), + args[0], + args[1], + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/pep/keeper/contract.go b/x/pep/keeper/contract.go index a2c3b7e7..1efd87c7 100644 --- a/x/pep/keeper/contract.go +++ b/x/pep/keeper/contract.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "encoding/json" "cosmossdk.io/store/prefix" storetypes "cosmossdk.io/store/types" @@ -90,7 +91,7 @@ func (k Keeper) GetAllContractEntries(ctx context.Context) (list []types.Registe func (k Keeper) ExecuteContract(ctx sdk.Context, contractAddr string, msg types.ExecuteContractMsg) { addr := sdk.MustAccAddressFromBech32(contractAddr) - msgBytes, err := msg.Marshal() + msgBytes, err := json.Marshal(msg) if err != nil { k.logger.Error("error marshalling msg for contract: %s", contractAddr) return @@ -99,6 +100,6 @@ func (k Keeper) ExecuteContract(ctx sdk.Context, contractAddr string, msg types. wasmAddr := authtypes.NewModuleAddress(wasmtypes.ModuleName) _, err = k.wasmKeeper.Execute(ctx, addr, wasmAddr, msgBytes, sdk.Coins{}) if err != nil { - k.logger.Error("error executing contract: %s", contractAddr) + k.logger.Error("error executing contract: %s; error: %v", contractAddr, err) } } diff --git a/x/pep/module/autocli.go b/x/pep/module/autocli.go index cb664282..3f96644c 100644 --- a/x/pep/module/autocli.go +++ b/x/pep/module/autocli.go @@ -77,7 +77,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcMethod: "DecryptData", Use: "decrypt-data [pubkey] [aggr-keyshare] [encrypted-data]", Short: "Query decrypt-data", - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "pubkey"}, {ProtoField: "aggrKeyshare"}, {ProtoField: "encryptedData"}}, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "pubkey"}, {ProtoField: "aggr_keyshare"}, {ProtoField: "encrypted_data"}}, }, // this line is used by ignite scaffolding # autocli/query diff --git a/x/pep/types/msg_register_contract.go b/x/pep/types/msg_register_contract.go new file mode 100644 index 00000000..9fc2fb31 --- /dev/null +++ b/x/pep/types/msg_register_contract.go @@ -0,0 +1,33 @@ +package types + +import ( + sdkioerrors "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const TypeMsgRegisterContract = "register_contract" + +var _ sdk.Msg = &MsgRegisterContract{} + +func NewMsgRegisterContract(creator string, contractAddr string, identity string) *MsgRegisterContract { + return &MsgRegisterContract{ + Creator: creator, + ContractAddress: contractAddr, + Identity: identity, + } +} + +func (msg *MsgRegisterContract) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return sdkioerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) + } + + _, err = sdk.AccAddressFromBech32(msg.ContractAddress) + if err != nil { + return sdkioerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid contract address (%s)", err) + } + + return nil +} diff --git a/x/pep/types/query.pb.go b/x/pep/types/query.pb.go index 63b70e3e..bb0491f5 100644 --- a/x/pep/types/query.pb.go +++ b/x/pep/types/query.pb.go @@ -1046,8 +1046,8 @@ func (m *QueryShowPrivateKeyshareReqResponse) GetEncryptedKeyshares() []*types.E type QueryDecryptDataRequest struct { Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` - AggrKeyshare string `protobuf:"bytes,2,opt,name=aggrKeyshare,proto3" json:"aggrKeyshare,omitempty"` - EncryptedData string `protobuf:"bytes,3,opt,name=encryptedData,proto3" json:"encryptedData,omitempty"` + AggrKeyshare string `protobuf:"bytes,2,opt,name=aggr_keyshare,json=aggrKeyshare,proto3" json:"aggr_keyshare,omitempty"` + EncryptedData string `protobuf:"bytes,3,opt,name=encrypted_data,json=encryptedData,proto3" json:"encrypted_data,omitempty"` } func (m *QueryDecryptDataRequest) Reset() { *m = QueryDecryptDataRequest{} } @@ -1178,92 +1178,92 @@ func init() { func init() { proto.RegisterFile("fairyring/pep/query.proto", fileDescriptor_dd36cf23112e8be0) } var fileDescriptor_dd36cf23112e8be0 = []byte{ - // 1349 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x98, 0xcd, 0x6f, 0xe3, 0xc4, - 0x1b, 0xc7, 0xeb, 0xee, 0x36, 0xdb, 0x4e, 0xda, 0xea, 0xf7, 0x9b, 0xed, 0x4b, 0xea, 0xdd, 0xa6, - 0xdd, 0xe9, 0x2b, 0x11, 0xc4, 0x6a, 0xbb, 0x07, 0xa8, 0xb8, 0xa4, 0xf4, 0x85, 0xa5, 0x2b, 0x68, - 0x43, 0xe1, 0xb0, 0x97, 0x68, 0x12, 0x0f, 0x8e, 0xd5, 0xc4, 0x76, 0x6c, 0xa7, 0x9b, 0x10, 0x45, - 0x42, 0x7b, 0xe1, 0xc2, 0x01, 0x89, 0x3b, 0xe2, 0xb8, 0x07, 0x24, 0xb8, 0xee, 0x19, 0x0e, 0x7b, - 0x5c, 0x89, 0x0b, 0x27, 0x84, 0x5a, 0x24, 0x2e, 0xfc, 0x11, 0xc8, 0xe3, 0x67, 0x12, 0xdb, 0x71, - 0x92, 0x56, 0xf4, 0x52, 0xd5, 0x33, 0xcf, 0xcb, 0xe7, 0x79, 0x66, 0xfc, 0x7c, 0xdd, 0xa2, 0x85, - 0x2f, 0xa8, 0x6e, 0x37, 0x6d, 0xdd, 0xd0, 0x14, 0x8b, 0x59, 0x4a, 0xad, 0xce, 0xec, 0x66, 0xd6, - 0xb2, 0x4d, 0xd7, 0xc4, 0x53, 0x9d, 0xad, 0xac, 0xc5, 0x2c, 0xf9, 0xff, 0xb4, 0xaa, 0x1b, 0xa6, - 0xc2, 0x7f, 0xfa, 0x16, 0xf2, 0x8c, 0x66, 0x6a, 0x26, 0xff, 0x55, 0xf1, 0x7e, 0x83, 0xd5, 0x87, - 0x9a, 0x69, 0x6a, 0x15, 0xa6, 0x50, 0x4b, 0x57, 0xa8, 0x61, 0x98, 0x2e, 0x75, 0x75, 0xd3, 0x70, - 0x60, 0x37, 0x53, 0x32, 0x9d, 0xaa, 0xe9, 0x28, 0x45, 0xea, 0x30, 0x3f, 0x9d, 0x72, 0xb1, 0x55, - 0x64, 0x2e, 0xdd, 0x52, 0x2c, 0xaa, 0xe9, 0x06, 0x37, 0x06, 0x5b, 0x39, 0x0c, 0x67, 0x51, 0x9b, - 0x56, 0x45, 0x9c, 0xe5, 0xf0, 0x1e, 0x33, 0x4a, 0x76, 0xd3, 0x72, 0x99, 0x5a, 0x70, 0x1b, 0x60, - 0xb1, 0x18, 0xf1, 0x66, 0x56, 0xc1, 0x30, 0x8d, 0x12, 0x83, 0xed, 0xcd, 0xf0, 0x36, 0xd5, 0x34, - 0x9b, 0x69, 0xd4, 0x8b, 0x70, 0xce, 0x9a, 0x05, 0xa7, 0x4c, 0x6d, 0x61, 0xb9, 0xd2, 0xb5, 0x2c, - 0x99, 0xd5, 0xaa, 0x69, 0x28, 0x7c, 0x57, 0x2d, 0xb8, 0x4d, 0x8b, 0x09, 0x9e, 0x74, 0xb0, 0x2e, - 0x51, 0x51, 0xc9, 0xd4, 0xa1, 0x16, 0x32, 0x83, 0xf0, 0xa9, 0x57, 0xed, 0x09, 0x2f, 0x22, 0xcf, - 0x6a, 0x75, 0xe6, 0xb8, 0xe4, 0x13, 0x74, 0x3f, 0xb4, 0xea, 0x58, 0xa6, 0xe1, 0x30, 0xfc, 0x2e, - 0x4a, 0xf8, 0xc5, 0xa6, 0xa4, 0x65, 0x69, 0x33, 0xb9, 0x3d, 0x9b, 0x0d, 0x9d, 0x45, 0xd6, 0x37, - 0xdf, 0x9b, 0x78, 0xfd, 0xc7, 0xd2, 0xc8, 0xcb, 0xbf, 0x7f, 0xce, 0x48, 0x79, 0xb0, 0x27, 0xef, - 0xa0, 0x19, 0x1e, 0xf0, 0x98, 0x35, 0x39, 0x24, 0x24, 0xc2, 0xb3, 0x28, 0x61, 0xb3, 0x5a, 0x41, - 0x57, 0x79, 0xc4, 0x89, 0xfc, 0x98, 0xcd, 0x6a, 0x4f, 0x54, 0xf2, 0x0c, 0xcd, 0x46, 0xcc, 0x81, - 0x20, 0x87, 0xc6, 0xcf, 0x61, 0x0d, 0x18, 0xd6, 0x22, 0x0c, 0x47, 0xcc, 0x38, 0x30, 0x4a, 0x67, - 0x8d, 0x83, 0x06, 0x2b, 0xd5, 0xbd, 0x43, 0x3b, 0xad, 0xb3, 0x3a, 0xcb, 0x77, 0xdc, 0x08, 0x45, - 0xf3, 0x3c, 0x76, 0xae, 0x52, 0x89, 0xd2, 0x1c, 0x22, 0xd4, 0x3d, 0x6c, 0x88, 0xbf, 0x9e, 0xf5, - 0x3b, 0x98, 0xf5, 0x3a, 0x98, 0xf5, 0x2f, 0x22, 0xf4, 0x31, 0x7b, 0x42, 0x35, 0xe1, 0x9b, 0x0f, - 0x78, 0x92, 0x97, 0x12, 0x4a, 0xf5, 0xe6, 0x80, 0x12, 0x3e, 0x40, 0x13, 0x82, 0xc5, 0xeb, 0xe3, - 0x9d, 0xeb, 0xd7, 0xd0, 0xf5, 0xc3, 0x47, 0x21, 0xd2, 0x51, 0x4e, 0xba, 0x31, 0x94, 0xd4, 0x27, - 0x08, 0xa1, 0x7e, 0x8e, 0x64, 0x4e, 0x7a, 0xc4, 0xdc, 0x03, 0x71, 0x57, 0xcf, 0x1a, 0xa2, 0x21, - 0x04, 0x4d, 0xba, 0xd4, 0xd6, 0x98, 0xfb, 0x21, 0xd3, 0xb5, 0xb2, 0xcb, 0x5b, 0x72, 0x37, 0x1f, - 0x5a, 0xc3, 0x33, 0x68, 0x4c, 0x37, 0x54, 0xd6, 0xe0, 0x14, 0x77, 0xf3, 0xfe, 0x03, 0xa1, 0xe8, - 0x41, 0x6c, 0x5c, 0x68, 0xc2, 0x1e, 0x4a, 0xb2, 0xee, 0x32, 0xb4, 0x5a, 0x8e, 0xb4, 0x21, 0xe0, - 0xb8, 0x77, 0xd7, 0xbb, 0x53, 0xf9, 0xa0, 0x13, 0x51, 0x01, 0x3d, 0x57, 0xa9, 0xc4, 0xa0, 0xdf, - 0xd6, 0x59, 0xbe, 0x92, 0xa0, 0x92, 0x68, 0x1a, 0xa8, 0xe4, 0x14, 0xfd, 0x2f, 0x00, 0x95, 0xb3, - 0x6d, 0xda, 0x84, 0x53, 0x5d, 0xea, 0x5f, 0x0e, 0x37, 0x83, 0x9a, 0x7a, 0xdc, 0x6f, 0xef, 0x70, - 0x3f, 0x42, 0xab, 0x31, 0xe8, 0x87, 0xb6, 0x59, 0xf5, 0xcf, 0xee, 0x06, 0xc7, 0x4c, 0xbe, 0x44, - 0x6b, 0x43, 0x62, 0x0d, 0x6c, 0x88, 0xf4, 0x1f, 0x1a, 0x42, 0x64, 0x78, 0x9d, 0x9e, 0x52, 0x97, - 0x39, 0x6e, 0x88, 0x9d, 0xec, 0xa0, 0x85, 0x98, 0x3d, 0x60, 0x99, 0x43, 0x89, 0x72, 0xb0, 0x24, - 0x78, 0x22, 0x3b, 0x30, 0x03, 0x8e, 0x98, 0x7b, 0xc2, 0xac, 0x8f, 0xbd, 0xf1, 0x2b, 0x7a, 0x91, - 0x42, 0xf7, 0xa8, 0xaa, 0xda, 0xcc, 0x71, 0x60, 0x24, 0x89, 0x47, 0xf2, 0x19, 0x50, 0x84, 0x9c, - 0x20, 0xd1, 0x7b, 0x68, 0xdc, 0x82, 0x35, 0x28, 0x76, 0x3e, 0x3a, 0x1b, 0x61, 0x1b, 0x8a, 0xec, - 0x98, 0x07, 0xe7, 0x51, 0x94, 0xe5, 0xb6, 0xee, 0xf0, 0xf7, 0x81, 0x79, 0x34, 0x04, 0xfd, 0xce, - 0x0d, 0xd0, 0x6f, 0xef, 0xa2, 0x76, 0x54, 0xa8, 0x5e, 0x3c, 0x66, 0x4d, 0x71, 0xb4, 0x3f, 0x49, - 0x42, 0x86, 0x60, 0x19, 0x88, 0x8f, 0xd1, 0x24, 0x2d, 0xb9, 0xfa, 0x05, 0xf3, 0xd7, 0xa1, 0x31, - 0x8f, 0x02, 0xd4, 0xbe, 0x1e, 0x66, 0x73, 0xc2, 0xaa, 0xa2, 0x97, 0x8e, 0x99, 0xb8, 0x5f, 0x21, - 0x67, 0x2f, 0x58, 0xcd, 0x9b, 0xae, 0x2a, 0x04, 0x1b, 0xed, 0x17, 0xec, 0x54, 0x58, 0x85, 0x83, - 0x05, 0x9d, 0xc9, 0x2e, 0x22, 0x1c, 0xf8, 0xd3, 0xb2, 0xf9, 0xfc, 0xc4, 0xd6, 0x2f, 0xa8, 0xcb, - 0x02, 0x1a, 0x23, 0x8e, 0x75, 0x06, 0xf9, 0x32, 0x17, 0xd6, 0xbc, 0x5f, 0x25, 0xb4, 0x32, 0xd0, - 0x19, 0xaa, 0x4f, 0xa1, 0x7b, 0x25, 0x9b, 0x51, 0xd7, 0xb4, 0xc5, 0x05, 0x85, 0xc7, 0x80, 0x98, - 0x8e, 0x06, 0x02, 0x7b, 0x2f, 0x81, 0x55, 0x2f, 0x9e, 0xb3, 0x66, 0xea, 0x0e, 0x5f, 0x86, 0x27, - 0x7c, 0x86, 0xee, 0x77, 0x3f, 0x4f, 0xba, 0x92, 0x34, 0xc6, 0xef, 0xc0, 0x4a, 0x6f, 0x03, 0x3a, - 0xaf, 0x6b, 0x87, 0x0a, 0xb3, 0xe8, 0x92, 0x43, 0x5a, 0x70, 0x9d, 0xf7, 0x19, 0xdf, 0xda, 0xa7, - 0x2e, 0x15, 0x75, 0x77, 0x41, 0xa4, 0x10, 0x08, 0x41, 0x93, 0xde, 0x67, 0x8e, 0x88, 0x01, 0xf4, - 0xa1, 0x35, 0xbc, 0x8a, 0xa6, 0x3a, 0xc9, 0xbc, 0x98, 0x50, 0x4b, 0x78, 0x91, 0xe4, 0xe0, 0x9e, - 0x87, 0x92, 0x43, 0xdf, 0xd6, 0xd0, 0xb4, 0xca, 0x44, 0xb9, 0xaa, 0x17, 0xc2, 0xa7, 0x98, 0xea, - 0xac, 0x7a, 0xe6, 0xdb, 0xff, 0x4c, 0xa1, 0x31, 0x1e, 0x03, 0x1b, 0x28, 0xe1, 0x7f, 0xd0, 0xe0, - 0x47, 0x91, 0x17, 0xa2, 0xf7, 0x8b, 0x49, 0x26, 0x83, 0x4c, 0x7c, 0x02, 0xb2, 0xf8, 0xe2, 0xb7, - 0xbf, 0xbe, 0x1b, 0x9d, 0xc7, 0xb3, 0x4a, 0xdc, 0x07, 0x24, 0xfe, 0x41, 0x42, 0xc9, 0xc0, 0x48, - 0xc4, 0x6f, 0xc5, 0x85, 0x8c, 0xd5, 0x69, 0x39, 0x73, 0x1d, 0x53, 0xa0, 0xd8, 0xe5, 0x14, 0x8f, - 0xf1, 0xb6, 0xd2, 0xff, 0x53, 0x55, 0x69, 0x05, 0x67, 0x7f, 0x5b, 0x69, 0x71, 0x51, 0x6f, 0xe3, - 0x6f, 0x24, 0x34, 0x1d, 0x9c, 0xda, 0x95, 0x4a, 0x3c, 0x65, 0xac, 0x24, 0xc7, 0x53, 0xc6, 0xcb, - 0x2a, 0x59, 0xe1, 0x94, 0x8b, 0xf8, 0xc1, 0x00, 0x4a, 0xfc, 0x4a, 0x42, 0xa9, 0x30, 0x4e, 0x57, - 0x8f, 0xf0, 0xce, 0xf0, 0x6c, 0x3d, 0x4a, 0x28, 0x3f, 0xbe, 0x99, 0x13, 0xc0, 0x6e, 0x73, 0xd8, - 0xb7, 0x71, 0xe6, 0xfa, 0x2d, 0xc5, 0x5f, 0x4b, 0x68, 0x32, 0xa8, 0x59, 0x78, 0x23, 0x2e, 0x75, - 0x8c, 0xe2, 0xc9, 0x9b, 0xc3, 0x0d, 0x81, 0x6b, 0x95, 0x73, 0xa5, 0xf1, 0xc3, 0x08, 0x57, 0x85, - 0x1b, 0x17, 0x7c, 0x31, 0xf4, 0x48, 0xc6, 0xc5, 0x88, 0xc7, 0xeb, 0x7d, 0x6e, 0x52, 0x44, 0x9a, - 0xe4, 0x8d, 0xa1, 0x76, 0xc0, 0x90, 0xe1, 0x0c, 0xab, 0x98, 0x28, 0x7d, 0xfe, 0xee, 0x51, 0x5a, - 0x20, 0xb0, 0x6d, 0xfc, 0x95, 0x84, 0x92, 0x22, 0x80, 0x77, 0xb7, 0xd6, 0xfb, 0x9c, 0xc6, 0xb5, - 0x60, 0x62, 0xb4, 0x8e, 0x2c, 0x73, 0x18, 0x19, 0xa7, 0xfa, 0xc1, 0x60, 0x13, 0x25, 0x40, 0x18, - 0xe2, 0x5f, 0xfa, 0xa0, 0x40, 0xf5, 0x79, 0xe9, 0x43, 0x62, 0x45, 0xd2, 0x3c, 0x65, 0x0a, 0xcf, - 0x45, 0x53, 0xd6, 0x8b, 0xde, 0xd0, 0xc5, 0x2f, 0x24, 0x94, 0x0c, 0x8c, 0x79, 0xbc, 0x12, 0x17, - 0x33, 0xf2, 0x87, 0x8a, 0xbc, 0x3a, 0xd8, 0x08, 0x52, 0x6f, 0xf2, 0xd4, 0x04, 0x2f, 0x47, 0x52, - 0x8b, 0x59, 0xaf, 0xb4, 0x7c, 0xb9, 0x68, 0x7b, 0x10, 0xd3, 0x81, 0x1c, 0x83, 0x7a, 0x1f, 0x45, - 0xd9, 0x18, 0x6a, 0x07, 0x34, 0x4b, 0x9c, 0x66, 0x01, 0xcf, 0xf7, 0xa1, 0xc1, 0xbf, 0x48, 0x68, - 0x2e, 0x5e, 0xfb, 0xf0, 0x56, 0x5c, 0x92, 0x81, 0x22, 0x2b, 0x6f, 0xdf, 0xc4, 0x05, 0x10, 0xf7, - 0x38, 0xe2, 0xfb, 0x78, 0x57, 0x39, 0xa4, 0xba, 0x5d, 0xac, 0x98, 0xa5, 0xf3, 0x08, 0xac, 0x53, - 0x36, 0x9f, 0x17, 0x2c, 0x3f, 0x42, 0x47, 0x33, 0x0b, 0x36, 0xab, 0xf1, 0x5e, 0x3e, 0x51, 0xdb, - 0xf8, 0x47, 0x09, 0x25, 0x03, 0xf2, 0x13, 0xdf, 0xc7, 0x5e, 0x71, 0x8c, 0xef, 0x63, 0x8c, 0x8e, - 0x91, 0xa7, 0x1c, 0xf2, 0x10, 0xef, 0xf7, 0x85, 0x04, 0x41, 0xe3, 0x22, 0xa7, 0xb4, 0x82, 0x32, - 0xda, 0x56, 0x5a, 0x21, 0xc1, 0x6c, 0xef, 0xed, 0xbf, 0xbe, 0x4c, 0x4b, 0x6f, 0x2e, 0xd3, 0xd2, - 0x9f, 0x97, 0x69, 0xe9, 0xdb, 0xab, 0xf4, 0xc8, 0x9b, 0xab, 0xf4, 0xc8, 0xef, 0x57, 0xe9, 0x91, - 0x67, 0x19, 0x4d, 0x77, 0xcb, 0xf5, 0xa2, 0xa7, 0xfe, 0xb1, 0x99, 0x1a, 0x3c, 0x17, 0xff, 0x5f, - 0x43, 0x31, 0xc1, 0xff, 0x99, 0xb0, 0xf3, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x79, 0xc5, 0x1b, - 0xde, 0xb7, 0x11, 0x00, 0x00, + // 1352 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x98, 0xcf, 0x6f, 0xe3, 0x44, + 0x14, 0xc7, 0xeb, 0x6e, 0x9b, 0x6d, 0x27, 0x6d, 0x05, 0xb3, 0xfd, 0x91, 0x7a, 0xb7, 0x69, 0x77, + 0xd2, 0x5f, 0x44, 0x10, 0xab, 0xed, 0x1e, 0xa0, 0xe2, 0x92, 0xd2, 0x1f, 0xbb, 0x14, 0x2d, 0x6d, + 0x28, 0x1c, 0xf6, 0x12, 0x4d, 0xec, 0xc1, 0xb1, 0x9a, 0xd8, 0x8e, 0xed, 0x74, 0x13, 0xa2, 0x48, + 0x68, 0x2f, 0x5c, 0x38, 0x20, 0x71, 0x47, 0x1c, 0xf7, 0x04, 0x5c, 0xf7, 0x0c, 0x87, 0x3d, 0xae, + 0xc4, 0x85, 0x13, 0x42, 0x2d, 0x12, 0x37, 0xfe, 0x06, 0xe4, 0xf1, 0x73, 0x62, 0x3b, 0x4e, 0xd2, + 0x8a, 0x5e, 0xaa, 0x7a, 0xe6, 0xfd, 0xf8, 0xbc, 0x37, 0xe3, 0xf7, 0x75, 0x8b, 0x16, 0xbf, 0xa4, + 0x9a, 0xd5, 0xb4, 0x34, 0x5d, 0x95, 0x4c, 0x66, 0x4a, 0xb5, 0x3a, 0xb3, 0x9a, 0x39, 0xd3, 0x32, + 0x1c, 0x03, 0x4f, 0x77, 0xb6, 0x72, 0x26, 0x33, 0xc5, 0xb7, 0x69, 0x55, 0xd3, 0x0d, 0x89, 0xff, + 0xf4, 0x2c, 0xc4, 0x59, 0xd5, 0x50, 0x0d, 0xfe, 0xab, 0xe4, 0xfe, 0x06, 0xab, 0x0f, 0x54, 0xc3, + 0x50, 0x2b, 0x4c, 0xa2, 0xa6, 0x26, 0x51, 0x5d, 0x37, 0x1c, 0xea, 0x68, 0x86, 0x6e, 0xc3, 0x6e, + 0x56, 0x36, 0xec, 0xaa, 0x61, 0x4b, 0x25, 0x6a, 0x33, 0x2f, 0x9d, 0x74, 0xb1, 0x55, 0x62, 0x0e, + 0xdd, 0x92, 0x4c, 0xaa, 0x6a, 0x3a, 0x37, 0x06, 0x5b, 0x31, 0x0c, 0x67, 0x52, 0x8b, 0x56, 0xfd, + 0x38, 0x2b, 0xe1, 0x3d, 0xa6, 0xcb, 0x56, 0xd3, 0x74, 0x98, 0x52, 0x74, 0x1a, 0x60, 0xb1, 0x14, + 0xf1, 0x66, 0x66, 0x51, 0x37, 0x74, 0x99, 0xc1, 0xf6, 0x66, 0x78, 0x9b, 0xaa, 0xaa, 0xc5, 0x54, + 0xea, 0x46, 0x38, 0x67, 0xcd, 0xa2, 0x5d, 0xa6, 0x96, 0x6f, 0x99, 0xe9, 0x5a, 0xca, 0x46, 0xb5, + 0x6a, 0xe8, 0x12, 0xdf, 0x55, 0x8a, 0x4e, 0xd3, 0x64, 0x3e, 0x4f, 0x3a, 0x58, 0x97, 0x5f, 0x91, + 0x6c, 0x68, 0x50, 0x0b, 0x99, 0x45, 0xf8, 0xd4, 0xad, 0xf6, 0x84, 0x17, 0x51, 0x60, 0xb5, 0x3a, + 0xb3, 0x1d, 0xf2, 0x29, 0xba, 0x17, 0x5a, 0xb5, 0x4d, 0x43, 0xb7, 0x19, 0x7e, 0x1f, 0x25, 0xbc, + 0x62, 0x53, 0xc2, 0x8a, 0xb0, 0x99, 0xdc, 0x9e, 0xcb, 0x85, 0xce, 0x22, 0xe7, 0x99, 0xef, 0x4d, + 0xbe, 0xfe, 0x73, 0x79, 0xe4, 0xe5, 0x3f, 0xbf, 0x64, 0x85, 0x02, 0xd8, 0x93, 0xf7, 0xd0, 0x2c, + 0x0f, 0x78, 0xcc, 0x9a, 0x1c, 0x12, 0x12, 0xe1, 0x39, 0x94, 0xb0, 0x58, 0xad, 0xa8, 0x29, 0x3c, + 0xe2, 0x64, 0x61, 0xdc, 0x62, 0xb5, 0x27, 0x0a, 0x79, 0x86, 0xe6, 0x22, 0xe6, 0x40, 0x90, 0x47, + 0x13, 0xe7, 0xb0, 0x06, 0x0c, 0x6b, 0x11, 0x86, 0x23, 0xa6, 0x1f, 0xe8, 0xf2, 0x59, 0xe3, 0xa0, + 0xc1, 0xe4, 0xba, 0x7b, 0x68, 0xa7, 0x75, 0x56, 0x67, 0x85, 0x8e, 0x1b, 0xa1, 0x68, 0x81, 0xc7, + 0xce, 0x57, 0x2a, 0x51, 0x9a, 0x43, 0x84, 0xba, 0x87, 0x0d, 0xf1, 0xd7, 0x73, 0x5e, 0x07, 0x73, + 0x6e, 0x07, 0x73, 0xde, 0x45, 0x84, 0x3e, 0xe6, 0x4e, 0xa8, 0xea, 0xfb, 0x16, 0x02, 0x9e, 0xe4, + 0xa5, 0x80, 0x52, 0xbd, 0x39, 0xa0, 0x84, 0x8f, 0xd0, 0xa4, 0xcf, 0xe2, 0xf6, 0xf1, 0xce, 0xf5, + 0x6b, 0xe8, 0xfa, 0xe1, 0xa3, 0x10, 0xe9, 0x28, 0x27, 0xdd, 0x18, 0x4a, 0xea, 0x11, 0x84, 0x50, + 0xbf, 0x40, 0x22, 0x27, 0x3d, 0x62, 0xce, 0x81, 0x7f, 0x57, 0xcf, 0x1a, 0x7e, 0x43, 0x08, 0x9a, + 0x72, 0xa8, 0xa5, 0x32, 0xe7, 0x31, 0xd3, 0xd4, 0xb2, 0xc3, 0x5b, 0x32, 0x56, 0x08, 0xad, 0xe1, + 0x59, 0x34, 0xae, 0xe9, 0x0a, 0x6b, 0x70, 0x8a, 0xb1, 0x82, 0xf7, 0x40, 0x28, 0xba, 0x1f, 0x1b, + 0x17, 0x9a, 0xb0, 0x87, 0x92, 0xac, 0xbb, 0x0c, 0xad, 0x16, 0x23, 0x6d, 0x08, 0x38, 0xee, 0x8d, + 0xb9, 0x77, 0xaa, 0x10, 0x74, 0x22, 0x0a, 0xa0, 0xe7, 0x2b, 0x95, 0x18, 0xf4, 0xdb, 0x3a, 0xcb, + 0x57, 0x02, 0x54, 0x12, 0x4d, 0x03, 0x95, 0x9c, 0xa2, 0xb7, 0x02, 0x50, 0x79, 0xcb, 0xa2, 0x4d, + 0x38, 0xd5, 0xe5, 0xfe, 0xe5, 0x70, 0x33, 0xa8, 0xa9, 0xc7, 0xfd, 0xf6, 0x0e, 0xf7, 0x63, 0xb4, + 0x1a, 0x83, 0x7e, 0x68, 0x19, 0x55, 0xef, 0xec, 0x6e, 0x70, 0xcc, 0xe4, 0x2b, 0xb4, 0x36, 0x24, + 0xd6, 0xc0, 0x86, 0x08, 0xff, 0xa3, 0x21, 0x44, 0x84, 0xd7, 0xe9, 0x13, 0xea, 0x30, 0xdb, 0x09, + 0xb1, 0x93, 0x1d, 0xb4, 0x18, 0xb3, 0x07, 0x2c, 0xf3, 0x28, 0x51, 0x0e, 0x96, 0x04, 0x4f, 0x64, + 0x07, 0x66, 0xc0, 0x11, 0x73, 0x4e, 0x98, 0xf9, 0xd4, 0x1d, 0xbf, 0x7e, 0x2f, 0x52, 0xe8, 0x2e, + 0x55, 0x14, 0x8b, 0xd9, 0x36, 0x8c, 0x24, 0xff, 0x91, 0x7c, 0x0e, 0x14, 0x21, 0x27, 0x48, 0xf4, + 0x01, 0x9a, 0x30, 0x61, 0x0d, 0x8a, 0x5d, 0x88, 0xce, 0x46, 0xd8, 0x86, 0x22, 0x3b, 0xe6, 0xc1, + 0x79, 0x14, 0x65, 0xb9, 0xad, 0x3b, 0xfc, 0x43, 0x60, 0x1e, 0x0d, 0x41, 0xbf, 0x73, 0x03, 0xf4, + 0xdb, 0xbb, 0xa8, 0x1d, 0x15, 0xaa, 0x97, 0x8e, 0x59, 0xd3, 0x3f, 0xda, 0x9f, 0x05, 0x5f, 0x86, + 0x60, 0x19, 0x88, 0x8f, 0xd1, 0x14, 0x95, 0x1d, 0xed, 0x82, 0x79, 0xeb, 0xd0, 0x98, 0x87, 0x01, + 0x6a, 0x4f, 0x0f, 0x73, 0x79, 0xdf, 0xaa, 0xa2, 0xc9, 0xc7, 0xcc, 0xbf, 0x5f, 0x21, 0x67, 0x37, + 0x58, 0xcd, 0x9d, 0xae, 0x0a, 0x04, 0x1b, 0xed, 0x17, 0xec, 0xd4, 0xb7, 0x0a, 0x07, 0x0b, 0x3a, + 0x93, 0x5d, 0x44, 0x38, 0xf0, 0x67, 0x65, 0xe3, 0xf9, 0x89, 0xa5, 0x5d, 0x50, 0x87, 0x05, 0x34, + 0xc6, 0x3f, 0xd6, 0x59, 0xe4, 0xc9, 0x5c, 0x58, 0xf3, 0x7e, 0x13, 0x50, 0x66, 0xa0, 0x33, 0x54, + 0x9f, 0x42, 0x77, 0x65, 0x8b, 0x51, 0xc7, 0xb0, 0xfc, 0x0b, 0x0a, 0x8f, 0x01, 0x31, 0x1d, 0x0d, + 0x04, 0x76, 0x5f, 0x02, 0xb3, 0x5e, 0x3a, 0x67, 0xcd, 0xd4, 0x1d, 0xbe, 0x0c, 0x4f, 0xf8, 0x0c, + 0xdd, 0xeb, 0x7e, 0x9e, 0x74, 0x25, 0x69, 0x9c, 0xdf, 0x81, 0x4c, 0x6f, 0x03, 0x3a, 0xaf, 0x6b, + 0x87, 0x0a, 0xb3, 0xe8, 0x92, 0x4d, 0xda, 0x70, 0x9d, 0xf7, 0x19, 0xdf, 0xda, 0xa7, 0x0e, 0xf5, + 0xeb, 0xee, 0x82, 0x08, 0x21, 0x90, 0x0c, 0x9a, 0x76, 0x3f, 0x73, 0x3a, 0x0c, 0x80, 0x3f, 0xe5, + 0x2e, 0xfa, 0x81, 0xf1, 0x1a, 0x9a, 0xe9, 0xd2, 0x2a, 0xd4, 0xa1, 0x50, 0xcd, 0x74, 0x67, 0xd5, + 0x4d, 0x45, 0xf2, 0x70, 0xd3, 0x43, 0xe9, 0xa1, 0x73, 0x6b, 0x68, 0x46, 0x61, 0xa1, 0x10, 0x1e, + 0xc7, 0x74, 0x67, 0xd5, 0x35, 0xdf, 0xfe, 0x77, 0x1a, 0x8d, 0xf3, 0x18, 0x58, 0x47, 0x09, 0xef, + 0x93, 0x06, 0x3f, 0x8c, 0xbc, 0x12, 0xbd, 0xdf, 0x4c, 0x22, 0x19, 0x64, 0xe2, 0x11, 0x90, 0xa5, + 0x17, 0xbf, 0xff, 0xfd, 0xfd, 0xe8, 0x02, 0x9e, 0x93, 0xe2, 0x3e, 0x21, 0xf1, 0x8f, 0x02, 0x4a, + 0x06, 0x86, 0x22, 0x7e, 0x27, 0x2e, 0x64, 0xac, 0x52, 0x8b, 0xd9, 0xeb, 0x98, 0x02, 0xc5, 0x2e, + 0xa7, 0x78, 0x84, 0xb7, 0xa5, 0xfe, 0x1f, 0xab, 0x52, 0x2b, 0x38, 0xfd, 0xdb, 0x52, 0x8b, 0xcb, + 0x7a, 0x1b, 0x7f, 0x2b, 0xa0, 0x99, 0xe0, 0xdc, 0xae, 0x54, 0xe2, 0x29, 0x63, 0x45, 0x39, 0x9e, + 0x32, 0x5e, 0x58, 0x49, 0x86, 0x53, 0x2e, 0xe1, 0xfb, 0x03, 0x28, 0xf1, 0x2b, 0x01, 0xa5, 0xc2, + 0x38, 0x5d, 0x45, 0xc2, 0x3b, 0xc3, 0xb3, 0xf5, 0x68, 0xa1, 0xf8, 0xe8, 0x66, 0x4e, 0x00, 0xbb, + 0xcd, 0x61, 0xdf, 0xc5, 0xd9, 0xeb, 0xb7, 0x14, 0x7f, 0x23, 0xa0, 0xa9, 0xa0, 0x6a, 0xe1, 0x8d, + 0xb8, 0xd4, 0x31, 0x9a, 0x27, 0x6e, 0x0e, 0x37, 0x04, 0xae, 0x55, 0xce, 0x95, 0xc6, 0x0f, 0x22, + 0x5c, 0x15, 0x6e, 0x5c, 0xf4, 0xe4, 0xd0, 0x25, 0x99, 0xf0, 0x87, 0x3c, 0x5e, 0xef, 0x73, 0x93, + 0x22, 0xe2, 0x24, 0x6e, 0x0c, 0xb5, 0x03, 0x86, 0x2c, 0x67, 0x58, 0xc5, 0x44, 0xea, 0xf3, 0x97, + 0x8f, 0xd4, 0x02, 0x89, 0x6d, 0xe3, 0xaf, 0x05, 0x94, 0xf4, 0x03, 0xb8, 0x77, 0x6b, 0xbd, 0xcf, + 0x69, 0x5c, 0x0b, 0x26, 0x46, 0xed, 0xc8, 0x0a, 0x87, 0x11, 0x71, 0xaa, 0x1f, 0x0c, 0x36, 0x50, + 0x02, 0xa4, 0x21, 0xfe, 0xa5, 0x0f, 0x4a, 0x54, 0x9f, 0x97, 0x3e, 0x24, 0x57, 0x24, 0xcd, 0x53, + 0xa6, 0xf0, 0x7c, 0x34, 0x65, 0xbd, 0xe4, 0x8e, 0x3c, 0xfc, 0x42, 0x40, 0xc9, 0xc0, 0xa0, 0xc7, + 0x99, 0xb8, 0x98, 0x91, 0x3f, 0x55, 0xc4, 0xd5, 0xc1, 0x46, 0x90, 0x7a, 0x93, 0xa7, 0x26, 0x78, + 0x25, 0x92, 0xda, 0x9f, 0xb4, 0x52, 0xcb, 0x13, 0x8c, 0xb6, 0x0b, 0x31, 0x13, 0xc8, 0x31, 0xa8, + 0xf7, 0x51, 0x94, 0x8d, 0xa1, 0x76, 0x40, 0xb3, 0xcc, 0x69, 0x16, 0xf1, 0x42, 0x1f, 0x1a, 0xfc, + 0xab, 0x80, 0xe6, 0xe3, 0xd5, 0x0f, 0x6f, 0xc5, 0x25, 0x19, 0x28, 0xb3, 0xe2, 0xf6, 0x4d, 0x5c, + 0x00, 0x71, 0x8f, 0x23, 0x7e, 0x88, 0x77, 0xa5, 0x43, 0xaa, 0x59, 0xa5, 0x8a, 0x21, 0x9f, 0x47, + 0x60, 0xed, 0xb2, 0xf1, 0xbc, 0x68, 0x7a, 0x11, 0x3a, 0x8a, 0x55, 0xb4, 0x58, 0x8d, 0xf7, 0xf2, + 0x89, 0xd2, 0xc6, 0x3f, 0x09, 0x28, 0x19, 0x90, 0x9f, 0xf8, 0x3e, 0xf6, 0xca, 0x63, 0x7c, 0x1f, + 0x63, 0x74, 0x8c, 0x3c, 0xe5, 0x90, 0x8f, 0xf1, 0x61, 0x5f, 0x48, 0x10, 0x34, 0x2e, 0x72, 0x52, + 0x2b, 0x24, 0xae, 0x6d, 0xa9, 0x15, 0xd6, 0xd1, 0xf6, 0xde, 0xfe, 0xeb, 0xcb, 0xb4, 0xf0, 0xe6, + 0x32, 0x2d, 0xfc, 0x75, 0x99, 0x16, 0xbe, 0xbb, 0x4a, 0x8f, 0xbc, 0xb9, 0x4a, 0x8f, 0xfc, 0x71, + 0x95, 0x1e, 0x79, 0x96, 0x55, 0x35, 0xa7, 0x5c, 0x2f, 0xb9, 0x5f, 0x00, 0xb1, 0xb9, 0x1a, 0x3c, + 0x1b, 0xff, 0x7f, 0x43, 0x29, 0xc1, 0xff, 0xa1, 0xb0, 0xf3, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xa1, 0x79, 0x33, 0x8c, 0xbb, 0x11, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pep/types/query.pb.gw.go b/x/pep/types/query.pb.gw.go index 55cdab4c..4f915f65 100644 --- a/x/pep/types/query.pb.gw.go +++ b/x/pep/types/query.pb.gw.go @@ -488,7 +488,7 @@ func local_request_Query_ShowPrivateKeyshareReq_0(ctx context.Context, marshaler } var ( - filter_Query_DecryptData_0 = &utilities.DoubleArray{Encoding: map[string]int{"aggrKeyshare": 0, "encryptedData": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} + filter_Query_DecryptData_0 = &utilities.DoubleArray{Encoding: map[string]int{"aggr_keyshare": 0, "encrypted_data": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} ) func request_Query_DecryptData_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -502,26 +502,26 @@ func request_Query_DecryptData_0(ctx context.Context, marshaler runtime.Marshale _ = err ) - val, ok = pathParams["aggrKeyshare"] + val, ok = pathParams["aggr_keyshare"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "aggrKeyshare") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "aggr_keyshare") } protoReq.AggrKeyshare, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "aggrKeyshare", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "aggr_keyshare", err) } - val, ok = pathParams["encryptedData"] + val, ok = pathParams["encrypted_data"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "encryptedData") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "encrypted_data") } protoReq.EncryptedData, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "encryptedData", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "encrypted_data", err) } if err := req.ParseForm(); err != nil { @@ -547,26 +547,26 @@ func local_request_Query_DecryptData_0(ctx context.Context, marshaler runtime.Ma _ = err ) - val, ok = pathParams["aggrKeyshare"] + val, ok = pathParams["aggr_keyshare"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "aggrKeyshare") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "aggr_keyshare") } protoReq.AggrKeyshare, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "aggrKeyshare", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "aggr_keyshare", err) } - val, ok = pathParams["encryptedData"] + val, ok = pathParams["encrypted_data"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "encryptedData") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "encrypted_data") } protoReq.EncryptedData, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "encryptedData", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "encrypted_data", err) } if err := req.ParseForm(); err != nil { @@ -1170,7 +1170,7 @@ var ( pattern_Query_ShowPrivateKeyshareReq_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"Fairblock", "fairyring", "pep", "show_private_keyshare_req", "reqId"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DecryptData_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"Fairblock", "fairyring", "pep", "decrypt_data", "aggrKeyshare", "encryptedData"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_DecryptData_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"Fairblock", "fairyring", "pep", "decrypt_data", "aggr_keyshare", "encrypted_data"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( From dcc90df163c0346d5044880a47467656601ac019 Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Fri, 27 Sep 2024 13:51:34 +0530 Subject: [PATCH 13/41] removing misnomer error --- x/keyshare/keeper/msg_create_general_key_share.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/keyshare/keeper/msg_create_general_key_share.go b/x/keyshare/keeper/msg_create_general_key_share.go index a720b4a9..238622fd 100644 --- a/x/keyshare/keeper/msg_create_general_key_share.go +++ b/x/keyshare/keeper/msg_create_general_key_share.go @@ -67,7 +67,7 @@ func (k msgServer) CreateGeneralKeyShare(goCtx context.Context, msg *types.MsgCr return nil, types.ErrKeyShareRequestNotFound.Wrapf(", got id value: %s", msg.IdValue) } if keyShareReq.AggrKeyshare != "" { - return nil, types.ErrAggKeyAlreadyExists.Wrapf(", identity: %s, Aggregated key: %s", msg.IdValue, keyShareReq.AggrKeyshare) + return &types.MsgCreateGeneralKeyShareResponse{}, nil } } From 2808974b07a6914a2b16be6134512267160297b6 Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Mon, 30 Sep 2024 19:53:57 +0530 Subject: [PATCH 14/41] testing contract --- fairyring_contract/Cargo.lock | 1446 +++++++++++++++-- fairyring_contract/Cargo.toml | 44 +- fairyring_contract/proto/buf.gen.rust.yaml | 11 + fairyring_contract/proto/buf.lock | 53 + fairyring_contract/proto/buf.yaml | 27 + fairyring_contract/proto/pep.proto | 25 + fairyring_contract/src/contract.rs | 44 +- fairyring_contract/src/fairyring.common.rs | 76 + .../src/fairyring.keyshare.module.rs | 10 + fairyring_contract/src/fairyring.keyshare.rs | 683 ++++++++ .../src/fairyring.keyshare.tonic.rs | 799 +++++++++ .../src/fairyring.pep.module.rs | 10 + fairyring_contract/src/fairyring.pep.rs | 340 ++++ fairyring_contract/src/fairyring.pep.tonic.rs | 581 +++++++ fairyring_contract/src/lib.rs | 5 + fairyring_contract/src/msg.rs | 5 - 16 files changed, 3999 insertions(+), 160 deletions(-) create mode 100644 fairyring_contract/proto/buf.gen.rust.yaml create mode 100644 fairyring_contract/proto/buf.lock create mode 100644 fairyring_contract/proto/buf.yaml create mode 100644 fairyring_contract/proto/pep.proto create mode 100644 fairyring_contract/src/fairyring.common.rs create mode 100644 fairyring_contract/src/fairyring.keyshare.module.rs create mode 100644 fairyring_contract/src/fairyring.keyshare.rs create mode 100644 fairyring_contract/src/fairyring.keyshare.tonic.rs create mode 100644 fairyring_contract/src/fairyring.pep.module.rs create mode 100644 fairyring_contract/src/fairyring.pep.rs create mode 100644 fairyring_contract/src/fairyring.pep.tonic.rs diff --git a/fairyring_contract/Cargo.lock b/fairyring_contract/Cargo.lock index 3a73b6a7..4b43fdd1 100644 --- a/fairyring_contract/Cargo.lock +++ b/fairyring_contract/Cargo.lock @@ -2,17 +2,39 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" -version = "0.7.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "getrandom", + "cfg-if", "once_cell", "version_check", + "zerocopy", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "anyhow" version = "1.0.89" @@ -20,38 +42,251 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] -name = "base16ct" -version = "0.2.0" +name = "ark-bls12-381" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] [[package]] -name = "base64" -version = "0.21.7" +name = "ark-ec" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "rayon", + "zeroize", +] [[package]] -name = "base64ct" -version = "1.6.0" +name = "ark-ff" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rayon", + "rustc_version", + "zeroize", +] [[package]] -name = "bech32" -version = "0.9.1" +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] [[package]] -name = "block-buffer" -version = "0.9.0" +name = "ark-poly" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" dependencies = [ - "generic-array", + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", + "rayon", ] +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "axum" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 1.0.1", + "tower 0.5.1", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.1", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + [[package]] name = "block-buffer" version = "0.10.4" @@ -63,9 +298,9 @@ dependencies = [ [[package]] name = "bnum" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" +checksum = "3e31ea183f6ee62ac8b8a8cf7feddd766317adfb13ff469de57ce033efd6a790" [[package]] name = "byteorder" @@ -79,6 +314,15 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +[[package]] +name = "cc" +version = "1.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17" +dependencies = [ + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -91,69 +335,127 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "cosmwasm-core" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6ceb8624260d0d3a67c4e1a1d43fc7e9406720afbcb124521501dd138f90aa" + [[package]] name = "cosmwasm-crypto" -version = "1.5.8" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58535cbcd599b3c193e3967c8292fe1dbbb5de7c2a2d87380661091dd4744044" +checksum = "4125381e5fd7fefe9f614640049648088015eca2b60d861465329a5d87dfa538" dependencies = [ - "digest 0.10.7", + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "cosmwasm-core", + "digest", + "ecdsa", "ed25519-zebra", "k256", - "rand_core 0.6.4", + "num-traits", + "p256", + "rand_core", + "rayon", + "sha2", "thiserror", ] [[package]] name = "cosmwasm-derive" -version = "1.5.8" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e07de16c800ac82fd188d055ecdb923ead0cf33960d3350089260bb982c09f" +checksum = "1b5658b1dc64e10b56ae7a449f678f96932a96f6cfad1769d608d1d1d656480a" dependencies = [ - "syn 1.0.109", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "cosmwasm-schema" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86b4d949b6041519c58993a73f4bbfba8083ba14f7001eae704865a09065845" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ef1b5835a65fcca3ab8b9a02b4f4dacc78e233a5c2f20b270efb9db0666d12" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", ] [[package]] name = "cosmwasm-std" -version = "1.5.8" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c21fde95ccd20044a23c0ac6fd8c941f3e8c158169dc94b5aa6491a2d9551a8d" +checksum = "70eb7ab0c1e99dd6207496963ba2a457c4128ac9ad9c72a83f8d9808542b849b" dependencies = [ "base64", "bech32", "bnum", + "cosmwasm-core", "cosmwasm-crypto", "cosmwasm-derive", - "derivative", - "forward_ref", + "derive_more", "hex", + "rand_core", "schemars", "serde", "serde-json-wasm", - "sha2 0.10.8", + "sha2", "static_assertions", "thiserror", ] [[package]] -name = "cosmwasm-storage" -version = "1.5.2" +name = "cpufeatures" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66de2ab9db04757bcedef2b5984fbe536903ada4a8a9766717a4a71197ef34f6" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ - "cosmwasm-std", - "serde", + "libc", ] [[package]] -name = "cpufeatures" -version = "0.2.14" +name = "crossbeam-deque" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "libc", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -161,7 +463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core 0.6.4", + "rand_core", "subtle", "zeroize", ] @@ -178,26 +480,73 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.0" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", "subtle", "zeroize", ] +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "cw-multi-test" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0ae276e7a06ad1b7e7da78a3d68aba80634cde30ee7fe8259a94e653603fef8" +dependencies = [ + "anyhow", + "bech32", + "cosmwasm-std", + "cw-storage-plus", + "cw-utils", + "derivative", + "itertools 0.13.0", + "prost", + "schemars", + "serde", + "sha2", + "thiserror", +] + [[package]] name = "cw-storage-plus" -version = "0.11.1" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f13360e9007f51998d42b1bc6b7fa0141f74feae61ed5fd1e5b0a89eec7b5de1" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d7ee1963302b0ac2a9d42fe0faec826209c17452bfd36fbfd9d002a88929261" +checksum = "07dfee7f12f802431a856984a32bce1cb7da1e6c006b5409e3981035ce562dec" dependencies = [ + "cosmwasm-schema", "cosmwasm-std", "schemars", "serde", + "thiserror", ] [[package]] @@ -222,12 +571,24 @@ dependencies = [ ] [[package]] -name = "digest" -version = "0.9.0" +name = "derive_more" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "generic-array", + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "unicode-xid", ] [[package]] @@ -236,7 +597,7 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "const-oid", "crypto-common", "subtle", @@ -255,25 +616,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest 0.10.7", + "digest", "elliptic-curve", "rfc6979", "signature", - "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "signature", ] [[package]] name = "ed25519-zebra" -version = "3.1.0" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ "curve25519-dalek", - "hashbrown", + "ed25519", + "hashbrown 0.14.5", "hex", - "rand_core 0.6.4", - "serde", - "sha2 0.9.9", + "rand_core", + "sha2", "zeroize", ] @@ -291,29 +660,36 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest 0.10.7", + "digest", "ff", "generic-array", "group", - "pkcs8", - "rand_core 0.6.4", + "rand_core", "sec1", "subtle", "zeroize", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "fairyring_contract" version = "0.1.0" dependencies = [ + "cosmwasm-schema", "cosmwasm-std", - "cosmwasm-storage", + "cw-multi-test", "cw-storage-plus", "prost", "prost-types", "schemars", "serde", "thiserror", + "tonic", ] [[package]] @@ -322,15 +698,60 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core 0.6.4", + "rand_core", "subtle", ] [[package]] -name = "forward_ref" -version = "1.0.0" +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] [[package]] name = "generic-array" @@ -354,6 +775,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + [[package]] name = "group" version = "0.13.0" @@ -361,19 +788,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core 0.6.4", + "rand_core", "subtle", ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "h2" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.5.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hex" version = "0.4.3" @@ -386,7 +854,126 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", ] [[package]] @@ -398,6 +985,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -413,9 +1009,7 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", - "once_cell", - "sha2 0.10.8", - "signature", + "sha2", ] [[package]] @@ -424,32 +1018,175 @@ version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] -name = "opaque-debug" -version = "0.3.1" +name = "p256" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] [[package]] -name = "pkcs8" -version = "0.10.2" +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ - "der", - "spki", + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", ] [[package]] @@ -463,9 +1200,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.8.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", "prost-derive", @@ -473,24 +1210,23 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.8.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] name = "prost-types" -version = "0.8.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ - "bytes", "prost", ] @@ -504,10 +1240,25 @@ dependencies = [ ] [[package]] -name = "rand_core" -version = "0.5.1" +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] [[package]] name = "rand_core" @@ -518,6 +1269,26 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -528,6 +1299,84 @@ dependencies = [ "subtle", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + [[package]] name = "ryu" version = "1.0.18" @@ -555,7 +1404,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -567,11 +1416,16 @@ dependencies = [ "base16ct", "der", "generic-array", - "pkcs8", "subtle", "zeroize", ] +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "serde" version = "1.0.210" @@ -583,9 +1437,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.5.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" +checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" dependencies = [ "serde", ] @@ -598,7 +1452,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -609,7 +1463,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -626,27 +1480,20 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.9" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "digest", ] [[package]] -name = "sha2" -version = "0.10.8" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signature" @@ -654,20 +1501,41 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", + "digest", + "rand_core", ] [[package]] -name = "spki" -version = "0.7.3" +name = "slab" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "base64ct", - "der", + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "static_assertions" version = "1.1.0" @@ -693,15 +1561,27 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "thiserror" version = "1.0.64" @@ -719,9 +1599,186 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "prost", + "rustls-pemfile", + "socket2", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.17.0" @@ -734,20 +1791,149 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] diff --git a/fairyring_contract/Cargo.toml b/fairyring_contract/Cargo.toml index f13ef082..24d350fb 100644 --- a/fairyring_contract/Cargo.toml +++ b/fairyring_contract/Cargo.toml @@ -3,15 +3,45 @@ name = "fairyring_contract" version = "0.1.0" edition = "2018" +[lib] +crate-type = ["cdylib", "rlib"] + +[profile.release] +opt-level = 3 +debug = false +rpath = false +lto = true +debug-assertions = false +codegen-units = 1 +panic = 'abort' +incremental = false +overflow-checks = true + +[features] +# use library feature to disable all instantiate/execute/query exports +library = [] + +[package.metadata.scripts] +optimize = """docker run --rm -v "$(pwd)":/code \ + --mount type=volume,source="$(basename "$(pwd)")_cache",target=/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + cosmwasm/optimizer:0.15.0 +""" + [dependencies] -cosmwasm-std = "1.0" -cosmwasm-storage = "1.0" -cw-storage-plus = "0.11" +cosmwasm-schema = "2.1.0" +cosmwasm-std = { version = "2.1.0", features = [ + "cosmwasm_1_4", + # Enable this if you only deploy to chains that have CosmWasm 2.0 or higher + "cosmwasm_2_0", +] } +cw-storage-plus = "2.0.0" serde = { version = "1.0", features = ["derive"] } schemars = "0.8" thiserror = "1.0" -prost = "0.8" # Protobuf support -prost-types = "0.8" +prost = "0.13.3" # Protobuf support +prost-types = "0.13" +tonic = { version = "0.12.3", features = ["prost", "tls"] } -[lib] -crate-type = ["cdylib", "rlib"] \ No newline at end of file +[dev-dependencies] +cw-multi-test = "2.0.0" \ No newline at end of file diff --git a/fairyring_contract/proto/buf.gen.rust.yaml b/fairyring_contract/proto/buf.gen.rust.yaml new file mode 100644 index 00000000..ffa7062c --- /dev/null +++ b/fairyring_contract/proto/buf.gen.rust.yaml @@ -0,0 +1,11 @@ +version: v2 +plugins: + - remote: buf.build/community/neoeinstein-prost:v0.3.1 + out: ../fairblock-proto/src/prost/ + opt: + - extern_path=.cosmos=cosmos_sdk_proto::cosmos + - remote: buf.build/community/neoeinstein-tonic:v0.3.0 + out: ../fairblock-proto/src/prost/ + opt: + - no_server + - extern_path=.cosmos=cosmos_sdk_proto::cosmos \ No newline at end of file diff --git a/fairyring_contract/proto/buf.lock b/fairyring_contract/proto/buf.lock new file mode 100644 index 00000000..229e70e0 --- /dev/null +++ b/fairyring_contract/proto/buf.lock @@ -0,0 +1,53 @@ +# Generated by buf. DO NOT EDIT. +version: v1 +deps: + - remote: buf.build + owner: cosmos + repository: cosmos-proto + commit: 04467658e59e44bbb22fe568206e1f70 + digest: shake256:73a640bd60e0c523b0f8237ff34eab67c45a38b64bbbde1d80224819d272dbf316ac183526bd245f994af6608b025f5130483d0133c5edd385531326b5990466 + - remote: buf.build + owner: cosmos + repository: cosmos-sdk + commit: 05419252bcc241ea8023acf1ed4cadc5 + digest: shake256:1e54a48c19a8b59d35e0a7efa76402939f515f2d8005df099856f24c37c20a52800308f025abb8cffcd014d437b49707388aaca4865d9d063d8f25d5d4eb77d5 + - remote: buf.build + owner: cosmos + repository: gogo-proto + commit: 88ef6483f90f478fb938c37dde52ece3 + digest: shake256:89c45df2aa11e0cff97b0d695436713db3d993d76792e9f8dc1ae90e6ab9a9bec55503d48ceedd6b86069ab07d3041b32001b2bfe0227fa725dd515ff381e5ba + - remote: buf.build + owner: cosmos + repository: ibc + commit: 41fbc441e4d645119d275150719c5441 + digest: shake256:a61d3e152909abddc91dcc1aec8ac997007bebd48a7921bc243681c708e6c9068f6484aa7ed4e6ff60101d3422c98744a4a5294bbda6aacdba07f1dfa4291020 + - remote: buf.build + owner: cosmos + repository: ics23 + commit: dc427cb4519143d8996361c045a29ad7 + digest: shake256:f6611c56170e2cb6354fa6e367a225fed7b8b0defca3252f05e842fe311be46997680ebf57d8644b52c1f2cca49b366ffe89ce5e8db5fd055a15259c88e4e41e + - remote: buf.build + owner: cosmos + repository: interchain-security + commit: 8eccf50752a5463a9c59dbe8fc9d043a + digest: shake256:6d581ed256c376984e479f5d1dd440263833b76226dc19db53deaff09d5be4bed71a05610630e053630e27890fd9492100779e0c87ed5963559583c4ab77f152 + - remote: buf.build + owner: cosmwasm + repository: wasmd + commit: 5af8ba5098c74f67b7e900e1c6c3dcdf + digest: shake256:e270738e4950538ca149674972f8f0a8243bb795c7c5d2b5807348fec5aae42ddb646827ef08dd200ed65a4be0ab450162d48f1f5d0dae9446696ccb286b90db + - remote: buf.build + owner: googleapis + repository: googleapis + commit: e7f8d366f5264595bcc4cd4139af9973 + digest: shake256:e5e5f1c12f82e028ea696faa43b4f9dc6258a6d1226282962a8c8b282e10946281d815884f574bd279ebd9cd7588629beb3db17b892af6c33b56f92f8f67f509 + - remote: buf.build + owner: protocolbuffers + repository: wellknowntypes + commit: d59b7d45e69d4e129a1b797e2766f067 + digest: shake256:e4bb315f5a90aace88fe39709c831eda8eb0ce66b4cf947065888100b9867c2eb9a0f61f6b8d73c51b1fcccdfe8611090f55ce5db1aee6901ec9b4e6d8fa8e52 + - remote: buf.build + owner: tendermint + repository: tendermint + commit: 33ed361a90514289beabf3189e1d7665 + digest: shake256:038267e06294714fd883610626554b04a127b576b4e253befb4206cb72d5d3c1eeccacd4b9ec8e3fb891f7c14e1cb0f770c077d2989638995b0a61c85afedb1d diff --git a/fairyring_contract/proto/buf.yaml b/fairyring_contract/proto/buf.yaml new file mode 100644 index 00000000..98b607a0 --- /dev/null +++ b/fairyring_contract/proto/buf.yaml @@ -0,0 +1,27 @@ +breaking: + use: + - FILE +deps: +- buf.build/protocolbuffers/wellknowntypes +- buf.build/cosmos/cosmos-sdk +- buf.build/cosmos/cosmos-proto +- buf.build/cosmos/gogo-proto +- buf.build/googleapis/googleapis +- buf.build/cosmos/ics23 +- buf.build/cosmos/interchain-security +- buf.build/cosmos/ibc +- buf.build/cosmwasm/wasmd +lint: + except: + - UNARY_RPC + - COMMENT_FIELD + - SERVICE_SUFFIX + - PACKAGE_VERSION_SUFFIX + - RPC_REQUEST_STANDARD_NAME + ignore: + - tendermint + use: + - DEFAULT + - COMMENTS + - FILE_LOWER_SNAKE_CASE +version: v1 diff --git a/fairyring_contract/proto/pep.proto b/fairyring_contract/proto/pep.proto new file mode 100644 index 00000000..3609f35a --- /dev/null +++ b/fairyring_contract/proto/pep.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; + +package fairyring.pep; + +import "google/api/annotations.proto"; +option go_package = "github.com/Fairblock/fairyring/x/pep/types"; + +// Query defines the gRPC querier service. +service Query { + // Queries a list of DecryptData items. + rpc DecryptData (QueryDecryptDataRequest) returns (QueryDecryptDataResponse) { + option (google.api.http).get = "/Fairblock/fairyring/pep/decrypt_data/{aggr_keyshare}/{encrypted_data}"; + + } +} + +message QueryDecryptDataRequest { + string pubkey = 1; + string aggr_keyshare = 2; + string encrypted_data = 3; +} + +message QueryDecryptDataResponse { + string decrypted_data = 1; +} \ No newline at end of file diff --git a/fairyring_contract/src/contract.rs b/fairyring_contract/src/contract.rs index 66cf52f8..cfba3024 100644 --- a/fairyring_contract/src/contract.rs +++ b/fairyring_contract/src/contract.rs @@ -1,7 +1,8 @@ // contract.rs -use cosmwasm_std::{attr, entry_point, to_json_binary, Binary, QueryRequest, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; -use prost::Message; -use crate::msg::{ExecuteContractMsg, QueryMsg, QueryResponse, InstantiateMsg, QueryDecryptDataResponse}; +use cosmwasm_std::{attr, entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; +use crate::fairyring::pep::query_client::QueryClient; // The generated gRPC client +use crate::fairyring::pep::QueryDecryptDataRequest; // Generated message types +use crate::msg::{ExecuteContractMsg, QueryMsg, QueryResponse, InstantiateMsg}; use crate::state::STORED_DATA; #[entry_point] @@ -40,8 +41,8 @@ pub fn execute( #[entry_point] -pub fn query( - deps: Deps, +pub async fn query<'a>( + deps: Deps<'a, QueryMsg>, _env: Env, msg: QueryMsg, ) -> StdResult { @@ -68,7 +69,7 @@ pub fn query( } // Call the function to query the `pep` module - let response = query_pep_decrypt(deps, pubkey, aggr_keyshare, encrypted_data)?; + let response = query_pep_decrypt(deps, pubkey, aggr_keyshare, encrypted_data).await?; // Return the decrypted data in binary format to_json_binary(&response) @@ -101,25 +102,32 @@ pub fn instantiate( // Function to query the `DecryptData` RPC from your `pep` module -pub fn query_pep_decrypt( - deps: Deps, - pubkey : String, +pub async fn query_pep_decrypt<'a>( + _deps: Deps<'a, QueryMsg>, // Explicitly add lifetime `'a` + pubkey: String, aggr_keyshare: String, encrypted_data: String, ) -> StdResult { - // Create the custom query - let request = QueryRequest::Custom(QueryMsg::DecryptData { + // Create a gRPC connection to the `pep` module + let mut client = QueryClient::connect("http://localhost:9090") + .await + .map_err(|err| StdError::generic_err(format!("Failed to connect to gRPC server: {}", err)))?; + + // Create the request message + let request = QueryDecryptDataRequest { pubkey, aggr_keyshare, encrypted_data, - }); + }; - // Send the query - let raw_response: Binary = deps.querier.query(&request)?; + // Call the decrypt_data method + let response = client + .decrypt_data(request) + .await + .map_err(|err| StdError::generic_err(format!("gRPC query failed: {}", err)))?; - // Deserialize the protobuf response - let query_response = QueryDecryptDataResponse::decode(&*raw_response.0) - .map_err(|_| StdError::generic_err("Failed to decode protobuf response"))?; + // Extract the decrypted data from the response + let decrypted_data = response.into_inner().decrypted_data; - Ok(query_response.decrypted_data) + Ok(decrypted_data) } \ No newline at end of file diff --git a/fairyring_contract/src/fairyring.common.rs b/fairyring_contract/src/fairyring.common.rs new file mode 100644 index 00000000..279f1e37 --- /dev/null +++ b/fairyring_contract/src/fairyring.common.rs @@ -0,0 +1,76 @@ +// @generated +/// RequestAggrKeyshare defines a struct for the data payload +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RequestAggrKeyshare { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(message, optional, tag="4")] + pub estimated_delay: ::core::option::Option<::prost_types::Duration>, + #[prost(oneof="request_aggr_keyshare::Id", tags="2, 3")] + pub id: ::core::option::Option, +} +/// Nested message and enum types in `RequestAggrKeyshare`. +pub mod request_aggr_keyshare { + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Id { + #[prost(string, tag="2")] + ProposalId(::prost::alloc::string::String), + #[prost(string, tag="3")] + RequestId(::prost::alloc::string::String), + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RequestAggrKeyshareResponse { + #[prost(string, tag="1")] + pub identity: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub pubkey: ::prost::alloc::string::String, +} +/// GetAggrKeyshare defines a struct for the data payload +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAggrKeyshare { + #[prost(string, tag="3")] + pub identity: ::prost::alloc::string::String, + #[prost(oneof="get_aggr_keyshare::Id", tags="1, 2")] + pub id: ::core::option::Option, +} +/// Nested message and enum types in `GetAggrKeyshare`. +pub mod get_aggr_keyshare { + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Id { + #[prost(string, tag="1")] + ProposalId(::prost::alloc::string::String), + #[prost(string, tag="2")] + RequestId(::prost::alloc::string::String), + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAggrKeyshareResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ActivePublicKey { + #[prost(string, tag="1")] + pub public_key: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub creator: ::prost::alloc::string::String, + #[prost(uint64, tag="3")] + pub expiry: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueuedPublicKey { + #[prost(string, tag="1")] + pub public_key: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub creator: ::prost::alloc::string::String, + #[prost(uint64, tag="3")] + pub expiry: u64, +} +// @@protoc_insertion_point(module) diff --git a/fairyring_contract/src/fairyring.keyshare.module.rs b/fairyring_contract/src/fairyring.keyshare.module.rs new file mode 100644 index 00000000..e4db05ff --- /dev/null +++ b/fairyring_contract/src/fairyring.keyshare.module.rs @@ -0,0 +1,10 @@ +// @generated +/// Module is the config object for the module. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Module { + /// authority defines the custom module authority. If not set, defaults to the governance module. + #[prost(string, tag="1")] + pub authority: ::prost::alloc::string::String, +} +// @@protoc_insertion_point(module) diff --git a/fairyring_contract/src/fairyring.keyshare.rs b/fairyring_contract/src/fairyring.keyshare.rs new file mode 100644 index 00000000..d070e0f2 --- /dev/null +++ b/fairyring_contract/src/fairyring.keyshare.rs @@ -0,0 +1,683 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AggregatedKeyShare { + #[prost(uint64, tag="1")] + pub height: u64, + #[prost(string, tag="2")] + pub data: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AuthorizedAddress { + #[prost(string, tag="1")] + pub target: ::prost::alloc::string::String, + #[prost(bool, tag="2")] + pub is_authorized: bool, + #[prost(string, tag="3")] + pub authorized_by: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Commitments { + #[prost(string, repeated, tag="1")] + pub commitments: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GeneralKeyShare { + #[prost(string, tag="1")] + pub validator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub id_type: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub id_value: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub key_share: ::prost::alloc::string::String, + #[prost(uint64, tag="5")] + pub key_share_index: u64, + #[prost(uint64, tag="6")] + pub received_timestamp: u64, + #[prost(uint64, tag="7")] + pub received_block_height: u64, +} +/// Params defines the parameters for the module. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Params { + #[prost(uint64, tag="1")] + pub key_expiry: u64, + #[prost(uint64, tag="2")] + pub minimum_bonded: u64, + #[prost(uint64, tag="3")] + pub max_idled_block: u64, + #[prost(string, repeated, tag="4")] + pub trusted_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(bytes="vec", tag="5")] + pub slash_fraction_no_keyshare: ::prost::alloc::vec::Vec, + #[prost(bytes="vec", tag="6")] + pub slash_fraction_wrong_keyshare: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ValidatorSet { + #[prost(string, tag="1")] + pub index: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub validator: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub cons_addr: ::prost::alloc::string::String, + #[prost(bool, tag="4")] + pub is_active: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct KeyShare { + #[prost(string, tag="1")] + pub validator: ::prost::alloc::string::String, + #[prost(uint64, tag="2")] + pub block_height: u64, + #[prost(string, tag="3")] + pub key_share: ::prost::alloc::string::String, + #[prost(uint64, tag="4")] + pub key_share_index: u64, + #[prost(uint64, tag="5")] + pub received_timestamp: u64, + #[prost(uint64, tag="6")] + pub received_block_height: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EncryptedKeyShare { + #[prost(string, tag="1")] + pub data: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub validator: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ActivePubKey { + #[prost(string, tag="1")] + pub public_key: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub creator: ::prost::alloc::string::String, + #[prost(uint64, tag="3")] + pub expiry: u64, + #[prost(uint64, tag="4")] + pub number_of_validators: u64, + #[prost(message, repeated, tag="5")] + pub encrypted_key_shares: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueuedPubKey { + #[prost(string, tag="1")] + pub public_key: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub creator: ::prost::alloc::string::String, + #[prost(uint64, tag="3")] + pub expiry: u64, + #[prost(uint64, tag="4")] + pub number_of_validators: u64, + #[prost(message, repeated, tag="5")] + pub encrypted_key_shares: ::prost::alloc::vec::Vec, +} +/// GenesisState defines the keyshare module's genesis state. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GenesisState { + /// params defines all the parameters of the module. + #[prost(message, optional, tag="1")] + pub params: ::core::option::Option, + #[prost(string, tag="2")] + pub port_id: ::prost::alloc::string::String, + #[prost(message, repeated, tag="3")] + pub validator_set_list: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag="4")] + pub key_share_list: ::prost::alloc::vec::Vec, + /// this line is used by starport scaffolding # genesis/proto/state + #[prost(message, repeated, tag="5")] + pub aggregated_key_share_list: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="6")] + pub active_pub_key: ::core::option::Option, + #[prost(message, optional, tag="7")] + pub queued_pub_key: ::core::option::Option, + #[prost(message, repeated, tag="8")] + pub authorized_address_list: ::prost::alloc::vec::Vec, + #[prost(uint64, tag="9")] + pub request_count: u64, + #[prost(message, repeated, tag="10")] + pub general_key_share_list: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct KeysharePacketData { + #[prost(oneof="keyshare_packet_data::Packet", tags="1, 2, 3, 4, 5")] + pub packet: ::core::option::Option, +} +/// Nested message and enum types in `KeysharePacketData`. +pub mod keyshare_packet_data { + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Packet { + #[prost(message, tag="1")] + NoData(super::NoData), + #[prost(message, tag="2")] + RequestAggrKeysharePacket(super::RequestAggrKeysharePacketData), + #[prost(message, tag="3")] + GetAggrKeysharePacket(super::GetAggrKeysharePacketData), + #[prost(message, tag="4")] + AggrKeyshareDataPacket(super::AggrKeyshareDataPacketData), + #[prost(message, tag="5")] + CurrentKeysPacket(super::CurrentKeysPacketData), + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NoData { +} +/// RequestAggrKeysharePacketData defines a struct for the packet payload +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RequestAggrKeysharePacketData { + #[prost(string, tag="1")] + pub requester: ::prost::alloc::string::String, + #[prost(message, optional, tag="4")] + pub estimated_delay: ::core::option::Option<::prost_types::Duration>, + #[prost(oneof="request_aggr_keyshare_packet_data::Id", tags="2, 3")] + pub id: ::core::option::Option, +} +/// Nested message and enum types in `RequestAggrKeysharePacketData`. +pub mod request_aggr_keyshare_packet_data { + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Id { + #[prost(string, tag="2")] + ProposalId(::prost::alloc::string::String), + #[prost(string, tag="3")] + RequestId(::prost::alloc::string::String), + } +} +/// RequestAggrKeysharePacketAck defines a struct for the packet acknowledgment +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RequestAggrKeysharePacketAck { + #[prost(string, tag="1")] + pub identity: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub pubkey: ::prost::alloc::string::String, +} +/// GetAggrKeysharePacketData defines a struct for the packet payload +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAggrKeysharePacketData { + #[prost(string, tag="1")] + pub identity: ::prost::alloc::string::String, +} +/// GetAggrKeysharePacketAck defines a struct for the packet acknowledgment +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAggrKeysharePacketAck { +} +/// AggrKeyshareDataPacketData defines a struct for the packet payload +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AggrKeyshareDataPacketData { + #[prost(string, tag="1")] + pub identity: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub pubkey: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub aggr_keyshare: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub aggr_height: ::prost::alloc::string::String, + /// used for private governance + #[prost(string, tag="5")] + pub proposal_id: ::prost::alloc::string::String, + /// might be useful to destination chains to sort out the response + #[prost(string, tag="6")] + pub request_id: ::prost::alloc::string::String, + #[prost(uint64, tag="7")] + pub retries: u64, +} +/// AggrKeyshareDataPacketAck defines a struct for the packet acknowledgment +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AggrKeyshareDataPacketAck { +} +/// CurrentKeysPacketData defines a struct for the packet payload +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CurrentKeysPacketData { +} +/// CurrentKeysPacketAck defines a struct for the packet acknowledgment +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CurrentKeysPacketAck { + #[prost(message, optional, tag="1")] + pub active_key: ::core::option::Option, + #[prost(message, optional, tag="2")] + pub queued_key: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryVerifiableRandomnessQuery { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryVerifiableRandomnessResponse { + #[prost(string, tag="1")] + pub randomness: ::prost::alloc::string::String, + #[prost(uint64, tag="2")] + pub round: u64, +} +/// QueryParamsRequest is request type for the Query/Params RPC method. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryParamsRequest { +} +/// QueryParamsResponse is response type for the Query/Params RPC method. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryParamsResponse { + /// params holds all the parameters of this module. + #[prost(message, optional, tag="1")] + pub params: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryCommitmentsRequest { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryCommitmentsResponse { + #[prost(message, optional, tag="1")] + pub active_commitments: ::core::option::Option, + #[prost(message, optional, tag="2")] + pub queued_commitments: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetValidatorSetRequest { + #[prost(string, tag="1")] + pub index: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetValidatorSetResponse { + #[prost(message, optional, tag="1")] + pub validator_set: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllValidatorSetRequest { + #[prost(message, optional, tag="1")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllValidatorSetResponse { + #[prost(message, repeated, tag="1")] + pub validator_set: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetKeyShareRequest { + #[prost(string, tag="1")] + pub validator: ::prost::alloc::string::String, + #[prost(uint64, tag="2")] + pub block_height: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetKeyShareResponse { + #[prost(message, optional, tag="1")] + pub key_share: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllKeyShareRequest { + #[prost(message, optional, tag="1")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllKeyShareResponse { + #[prost(message, repeated, tag="1")] + pub key_share: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + pub pagination: ::core::option::Option, +} +/// this line is used by starport scaffolding # 3 +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetAggregatedKeyShareRequest { + #[prost(uint64, tag="1")] + pub height: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetAggregatedKeyShareResponse { + #[prost(message, optional, tag="1")] + pub aggregated_key_share: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllAggregatedKeyShareRequest { + #[prost(message, optional, tag="1")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllAggregatedKeyShareResponse { + #[prost(message, repeated, tag="1")] + pub aggregated_key_share: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryPubKeyRequest { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryPubKeyResponse { + #[prost(message, optional, tag="1")] + pub active_pub_key: ::core::option::Option, + #[prost(message, optional, tag="2")] + pub queued_pub_key: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetAuthorizedAddressRequest { + #[prost(string, tag="1")] + pub target: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetAuthorizedAddressResponse { + #[prost(message, optional, tag="1")] + pub authorized_address: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllAuthorizedAddressRequest { + #[prost(message, optional, tag="1")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllAuthorizedAddressResponse { + #[prost(message, repeated, tag="1")] + pub authorized_address: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetGeneralKeyShareRequest { + #[prost(string, tag="1")] + pub validator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub id_type: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub id_value: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetGeneralKeyShareResponse { + #[prost(message, optional, tag="1")] + pub general_key_share: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllGeneralKeyShareRequest { + #[prost(message, optional, tag="1")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllGeneralKeyShareResponse { + #[prost(message, repeated, tag="1")] + pub general_key_share: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct KeyShareRequest { + #[prost(string, tag="1")] + pub identity: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub pubkey: ::prost::alloc::string::String, + /// Used only when the request is made via IBC + #[prost(message, optional, tag="3")] + pub ibc_info: ::core::option::Option, + /// Used only when the request is made via IBC + #[prost(message, optional, tag="4")] + pub counterparty: ::core::option::Option, + #[prost(string, tag="5")] + pub aggr_keyshare: ::prost::alloc::string::String, + /// This is only used when the request is for private governance + #[prost(string, tag="6")] + pub proposal_id: ::prost::alloc::string::String, + /// might be useful to destination chains to sort out the response + #[prost(string, tag="7")] + pub request_id: ::prost::alloc::string::String, + #[prost(bool, tag="8")] + pub sent: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct IbcInfo { + #[prost(string, tag="1")] + pub client_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub connection_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub channel_id: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub port_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CounterPartyIbcInfo { + #[prost(string, tag="1")] + pub client_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub connection_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub channel_id: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub port_id: ::prost::alloc::string::String, +} +/// MsgUpdateParams is the Msg/UpdateParams request type. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgUpdateParams { + /// authority is the address that controls the module (defaults to x/gov unless overwritten). + #[prost(string, tag="1")] + pub authority: ::prost::alloc::string::String, + // params defines the module parameters to update. + + /// NOTE: All parameters must be supplied. + #[prost(message, optional, tag="2")] + pub params: ::core::option::Option, +} +/// MsgUpdateParamsResponse defines the response structure for executing a +/// MsgUpdateParams message. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgUpdateParamsResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgRegisterValidator { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgRegisterValidatorResponse { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgDeRegisterValidator { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgDeRegisterValidatorResponse { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgSendKeyshare { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub message: ::prost::alloc::string::String, + #[prost(uint64, tag="3")] + pub key_share_index: u64, + #[prost(uint64, tag="4")] + pub block_height: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgSendKeyshareResponse { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub keyshare: ::prost::alloc::string::String, + #[prost(uint64, tag="3")] + pub keyshare_index: u64, + #[prost(uint64, tag="4")] + pub block_height: u64, + #[prost(uint64, tag="5")] + pub received_block_height: u64, + #[prost(bool, tag="6")] + pub success: bool, + #[prost(string, tag="7")] + pub error_message: ::prost::alloc::string::String, +} +/// this line is used by starport scaffolding # proto/tx/message +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgCreateLatestPubKey { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub public_key: ::prost::alloc::string::String, + #[prost(string, repeated, tag="3")] + pub commitments: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(uint64, tag="4")] + pub number_of_validators: u64, + #[prost(message, repeated, tag="5")] + pub encrypted_key_shares: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgCreateLatestPubKeyResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgOverrideLatestPubKey { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub public_key: ::prost::alloc::string::String, + #[prost(string, repeated, tag="3")] + pub commitments: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(uint64, tag="4")] + pub number_of_validators: u64, + #[prost(message, repeated, tag="5")] + pub encrypted_key_shares: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgOverrideLatestPubKeyResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgCreateAuthorizedAddress { + #[prost(string, tag="1")] + pub target: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub creator: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgCreateAuthorizedAddressResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgUpdateAuthorizedAddress { + #[prost(string, tag="1")] + pub target: ::prost::alloc::string::String, + #[prost(bool, tag="2")] + pub is_authorized: bool, + #[prost(string, tag="3")] + pub creator: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgUpdateAuthorizedAddressResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgDeleteAuthorizedAddress { + #[prost(string, tag="1")] + pub target: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub creator: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgDeleteAuthorizedAddressResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgCreateGeneralKeyShare { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub id_type: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub id_value: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub key_share: ::prost::alloc::string::String, + #[prost(uint64, tag="5")] + pub key_share_index: u64, + #[prost(uint64, tag="6")] + pub received_timestamp: u64, + #[prost(uint64, tag="7")] + pub received_block_height: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgCreateGeneralKeyShareResponse { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub id_type: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub id_value: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub key_share: ::prost::alloc::string::String, + #[prost(uint64, tag="5")] + pub key_share_index: u64, + #[prost(uint64, tag="6")] + pub received_block_height: u64, + #[prost(bool, tag="7")] + pub success: bool, + #[prost(string, tag="8")] + pub error_message: ::prost::alloc::string::String, +} +include!("fairyring.keyshare.tonic.rs"); +// @@protoc_insertion_point(module) \ No newline at end of file diff --git a/fairyring_contract/src/fairyring.keyshare.tonic.rs b/fairyring_contract/src/fairyring.keyshare.tonic.rs new file mode 100644 index 00000000..7aff25c0 --- /dev/null +++ b/fairyring_contract/src/fairyring.keyshare.tonic.rs @@ -0,0 +1,799 @@ +// @generated +/// Generated client implementations. +pub mod query_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct QueryClient { + inner: tonic::client::Grpc, + } + impl QueryClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl QueryClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> QueryClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + QueryClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn params( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/Params", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Query", "Params")); + self.inner.unary(req, path, codec).await + } + pub async fn commitments( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/Commitments", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Query", "Commitments")); + self.inner.unary(req, path, codec).await + } + pub async fn validator_set( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/ValidatorSet", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Query", "ValidatorSet")); + self.inner.unary(req, path, codec).await + } + pub async fn validator_set_all( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/ValidatorSetAll", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Query", "ValidatorSetAll")); + self.inner.unary(req, path, codec).await + } + pub async fn key_share( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/KeyShare", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Query", "KeyShare")); + self.inner.unary(req, path, codec).await + } + pub async fn key_share_all( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/KeyShareAll", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Query", "KeyShareAll")); + self.inner.unary(req, path, codec).await + } + pub async fn aggregated_key_share( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/AggregatedKeyShare", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Query", "AggregatedKeyShare"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn aggregated_key_share_all( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/AggregatedKeyShareAll", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Query", "AggregatedKeyShareAll"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn pub_key( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/PubKey", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Query", "PubKey")); + self.inner.unary(req, path, codec).await + } + pub async fn authorized_address( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/AuthorizedAddress", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Query", "AuthorizedAddress"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn authorized_address_all( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/AuthorizedAddressAll", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Query", "AuthorizedAddressAll"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn general_key_share( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/GeneralKeyShare", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Query", "GeneralKeyShare")); + self.inner.unary(req, path, codec).await + } + pub async fn general_key_share_all( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/GeneralKeyShareAll", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Query", "GeneralKeyShareAll"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn verifiable_randomness( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Query/VerifiableRandomness", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Query", "VerifiableRandomness"), + ); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated client implementations. +pub mod msg_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct MsgClient { + inner: tonic::client::Grpc, + } + impl MsgClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl MsgClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> MsgClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + MsgClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn update_params( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/UpdateParams", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Msg", "UpdateParams")); + self.inner.unary(req, path, codec).await + } + pub async fn register_validator( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/RegisterValidator", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Msg", "RegisterValidator")); + self.inner.unary(req, path, codec).await + } + pub async fn de_register_validator( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/DeRegisterValidator", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Msg", "DeRegisterValidator"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn send_keyshare( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/SendKeyshare", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Msg", "SendKeyshare")); + self.inner.unary(req, path, codec).await + } + pub async fn create_latest_pub_key( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/CreateLatestPubKey", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.keyshare.Msg", "CreateLatestPubKey")); + self.inner.unary(req, path, codec).await + } + pub async fn override_latest_pub_key( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/OverrideLatestPubKey", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Msg", "OverrideLatestPubKey"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn create_authorized_address( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/CreateAuthorizedAddress", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Msg", "CreateAuthorizedAddress"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn update_authorized_address( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/UpdateAuthorizedAddress", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Msg", "UpdateAuthorizedAddress"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn delete_authorized_address( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/DeleteAuthorizedAddress", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Msg", "DeleteAuthorizedAddress"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn create_general_key_share( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.keyshare.Msg/CreateGeneralKeyShare", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.keyshare.Msg", "CreateGeneralKeyShare"), + ); + self.inner.unary(req, path, codec).await + } + } +} diff --git a/fairyring_contract/src/fairyring.pep.module.rs b/fairyring_contract/src/fairyring.pep.module.rs new file mode 100644 index 00000000..e4db05ff --- /dev/null +++ b/fairyring_contract/src/fairyring.pep.module.rs @@ -0,0 +1,10 @@ +// @generated +/// Module is the config object for the module. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Module { + /// authority defines the custom module authority. If not set, defaults to the governance module. + #[prost(string, tag="1")] + pub authority: ::prost::alloc::string::String, +} +// @@protoc_insertion_point(module) diff --git a/fairyring_contract/src/fairyring.pep.rs b/fairyring_contract/src/fairyring.pep.rs new file mode 100644 index 00000000..4f73a46a --- /dev/null +++ b/fairyring_contract/src/fairyring.pep.rs @@ -0,0 +1,340 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AggregatedKeyShare { + #[prost(uint64, tag="1")] + pub height: u64, + #[prost(string, tag="2")] + pub data: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub creator: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EncryptedTx { + #[prost(uint64, tag="1")] + pub target_height: u64, + #[prost(uint64, tag="2")] + pub index: u64, + #[prost(string, tag="3")] + pub data: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub creator: ::prost::alloc::string::String, + #[prost(message, optional, tag="5")] + pub charged_gas: ::core::option::Option, + #[prost(uint64, tag="6")] + pub processed_at_chain_height: u64, + #[prost(bool, tag="7")] + pub expired: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EncryptedTxArray { + #[prost(message, repeated, tag="1")] + pub encrypted_tx: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GeneralEncryptedTx { + #[prost(string, tag="1")] + pub identity: ::prost::alloc::string::String, + #[prost(uint64, tag="2")] + pub index: u64, + #[prost(string, tag="3")] + pub data: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub creator: ::prost::alloc::string::String, + #[prost(message, optional, tag="5")] + pub charged_gas: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GeneralEncryptedTxArray { + #[prost(message, repeated, tag="1")] + pub encrypted_tx: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GenEncTxExecutionQueue { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub request_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub identity: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub pubkey: ::prost::alloc::string::String, + #[prost(message, optional, tag="5")] + pub tx_list: ::core::option::Option, + #[prost(string, tag="6")] + pub aggr_keyshare: ::prost::alloc::string::String, +} +/// Params defines the parameters for the module. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Params { + #[prost(string, tag="1")] + pub keyshare_channel_id: ::prost::alloc::string::String, + #[prost(bool, tag="2")] + pub is_source_chain: bool, + #[prost(message, repeated, tag="3")] + pub trusted_counter_parties: ::prost::alloc::vec::Vec, + #[prost(string, repeated, tag="4")] + pub trusted_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(message, optional, tag="5")] + pub min_gas_price: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TrustedCounterParty { + #[prost(string, tag="1")] + pub client_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub connection_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub channel_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PepNonce { + #[prost(string, tag="1")] + pub address: ::prost::alloc::string::String, + #[prost(uint64, tag="2")] + pub nonce: u64, +} +/// GenesisState defines the pep module's genesis state. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GenesisState { + /// params defines all the parameters of the module. + #[prost(message, optional, tag="1")] + pub params: ::core::option::Option, + #[prost(string, tag="2")] + pub port_id: ::prost::alloc::string::String, + #[prost(message, repeated, tag="3")] + pub encrypted_tx_array: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag="4")] + pub pep_nonce_list: ::prost::alloc::vec::Vec, + /// this line is used by starport scaffolding # genesis/proto/state + #[prost(message, repeated, tag="6")] + pub aggregated_key_share_list: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="7")] + pub active_pub_key: ::core::option::Option, + #[prost(message, optional, tag="8")] + pub queued_pub_key: ::core::option::Option, + #[prost(uint64, tag="9")] + pub request_count: u64, +} +/// QueryParamsRequest is request type for the Query/Params RPC method. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryParamsRequest { +} +/// QueryParamsResponse is response type for the Query/Params RPC method. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryParamsResponse { + /// params holds all the parameters of this module. + #[prost(message, optional, tag="1")] + pub params: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryKeyshareRequest { + #[prost(string, tag="1")] + pub req_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryKeyshareResponse { + #[prost(message, optional, tag="1")] + pub keyshare: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllKeyshareRequest { + #[prost(message, optional, tag="1")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllKeyshareResponse { + #[prost(message, repeated, tag="1")] + pub keyshares: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetEncryptedTxRequest { + #[prost(uint64, tag="1")] + pub target_height: u64, + #[prost(uint64, tag="2")] + pub index: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetEncryptedTxResponse { + #[prost(message, optional, tag="1")] + pub encrypted_tx: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllEncryptedTxRequest { + #[prost(message, optional, tag="1")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllEncryptedTxResponse { + #[prost(message, repeated, tag="1")] + pub encrypted_tx_array: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllEncryptedTxFromHeightRequest { + #[prost(uint64, tag="1")] + pub target_height: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllEncryptedTxFromHeightResponse { + #[prost(message, optional, tag="1")] + pub encrypted_tx_array: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryLatestHeightRequest { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryLatestHeightResponse { + #[prost(uint64, tag="1")] + pub height: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetPepNonceRequest { + #[prost(string, tag="1")] + pub address: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryGetPepNonceResponse { + #[prost(message, optional, tag="1")] + pub pep_nonce: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllPepNonceRequest { + #[prost(message, optional, tag="1")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAllPepNonceResponse { + #[prost(message, repeated, tag="1")] + pub pep_nonce: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + pub pagination: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryPubKeyRequest { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryPubKeyResponse { + #[prost(message, optional, tag="1")] + pub active_pub_key: ::core::option::Option, + #[prost(message, optional, tag="2")] + pub queued_pub_key: ::core::option::Option, +} +/// MsgUpdateParams is the Msg/UpdateParams request type. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgUpdateParams { + /// authority is the address that controls the module (defaults to x/gov unless overwritten). + #[prost(string, tag="1")] + pub authority: ::prost::alloc::string::String, + /// params defines the module parameters to update. + /// + /// NOTE: All parameters must be supplied. + #[prost(message, optional, tag="2")] + pub params: ::core::option::Option, +} +/// MsgUpdateParamsResponse defines the response structure for executing a +/// MsgUpdateParams message. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgUpdateParamsResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgSubmitEncryptedTx { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub data: ::prost::alloc::string::String, + #[prost(uint64, tag="3")] + pub target_block_height: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgSubmitGeneralEncryptedTx { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub data: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub req_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgSubmitEncryptedTxResponse { +} +/// this line is used by starport scaffolding # proto/tx/message +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgCreateAggregatedKeyShare { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(uint64, tag="2")] + pub height: u64, + #[prost(string, tag="3")] + pub data: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgCreateAggregatedKeyShareResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgRequestGeneralKeyshare { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(message, optional, tag="2")] + pub estimated_delay: ::core::option::Option<::prost_types::Duration>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgRequestGeneralKeyshareResponse { + #[prost(string, tag="1")] + pub req_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgGetGeneralKeyshare { + #[prost(string, tag="1")] + pub creator: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub req_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MsgGetGeneralKeyshareResponse { +} +include!("fairyring.pep.tonic.rs"); +// @@protoc_insertion_point(module) \ No newline at end of file diff --git a/fairyring_contract/src/fairyring.pep.tonic.rs b/fairyring_contract/src/fairyring.pep.tonic.rs new file mode 100644 index 00000000..e33bd013 --- /dev/null +++ b/fairyring_contract/src/fairyring.pep.tonic.rs @@ -0,0 +1,581 @@ +// @generated +/// Generated client implementations. +pub mod query_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct QueryClient { + inner: tonic::client::Grpc, + } + impl QueryClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl QueryClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> QueryClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + QueryClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn params( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/Params", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Query", "Params")); + self.inner.unary(req, path, codec).await + } + pub async fn encrypted_tx( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/EncryptedTx", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Query", "EncryptedTx")); + self.inner.unary(req, path, codec).await + } + pub async fn encrypted_tx_all( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/EncryptedTxAll", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Query", "EncryptedTxAll")); + self.inner.unary(req, path, codec).await + } + pub async fn encrypted_tx_all_from_height( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/EncryptedTxAllFromHeight", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.pep.Query", "EncryptedTxAllFromHeight"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn latest_height( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/LatestHeight", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Query", "LatestHeight")); + self.inner.unary(req, path, codec).await + } + pub async fn pep_nonce( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/PepNonce", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Query", "PepNonce")); + self.inner.unary(req, path, codec).await + } + pub async fn pep_nonce_all( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/PepNonceAll", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Query", "PepNonceAll")); + self.inner.unary(req, path, codec).await + } + pub async fn pub_key( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/PubKey", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Query", "PubKey")); + self.inner.unary(req, path, codec).await + } + pub async fn keyshare_req( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/KeyshareReq", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Query", "KeyshareReq")); + self.inner.unary(req, path, codec).await + } + pub async fn keyshare_req_all( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Query/KeyshareReqAll", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Query", "KeyshareReqAll")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated client implementations. +pub mod msg_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct MsgClient { + inner: tonic::client::Grpc, + } + impl MsgClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl MsgClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> MsgClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + MsgClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn update_params( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Msg/UpdateParams", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Msg", "UpdateParams")); + self.inner.unary(req, path, codec).await + } + pub async fn submit_encrypted_tx( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Msg/SubmitEncryptedTx", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Msg", "SubmitEncryptedTx")); + self.inner.unary(req, path, codec).await + } + pub async fn submit_general_encrypted_tx( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Msg/SubmitGeneralEncryptedTx", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.pep.Msg", "SubmitGeneralEncryptedTx"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn create_aggregated_key_share( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Msg/CreateAggregatedKeyShare", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("fairyring.pep.Msg", "CreateAggregatedKeyShare"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn request_general_keyshare( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Msg/RequestGeneralKeyshare", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Msg", "RequestGeneralKeyshare")); + self.inner.unary(req, path, codec).await + } + pub async fn get_general_keyshare( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/fairyring.pep.Msg/GetGeneralKeyshare", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("fairyring.pep.Msg", "GetGeneralKeyshare")); + self.inner.unary(req, path, codec).await + } + } +} diff --git a/fairyring_contract/src/lib.rs b/fairyring_contract/src/lib.rs index 822c445f..b3ee57a3 100644 --- a/fairyring_contract/src/lib.rs +++ b/fairyring_contract/src/lib.rs @@ -2,6 +2,11 @@ pub mod contract; pub mod msg; pub mod state; pub mod error; +pub mod fairyring{ + pub mod pep { + include!("fairyring.pep.rs"); + } +} // use cosmwasm_std::{entry_point, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; diff --git a/fairyring_contract/src/msg.rs b/fairyring_contract/src/msg.rs index 5b6ca7b4..7e8d3e6a 100644 --- a/fairyring_contract/src/msg.rs +++ b/fairyring_contract/src/msg.rs @@ -32,11 +32,6 @@ pub struct QueryResponse { pub aggr_keyshare: String, } -#[derive(Clone, PartialEq, prost::Message)] -pub struct QueryDecryptDataResponse { - #[prost(string, tag = "1")] - pub decrypted_data: String, -} // Instantiate message #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] From b103bea15e615e058ad64cd9fb5ec3b8e43e2fed Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Mon, 30 Sep 2024 20:44:28 +0530 Subject: [PATCH 15/41] removing generated files --- fairyring_contract/Cargo.lock | 196 +++++ fairyring_contract/Cargo.toml | 4 + fairyring_contract/proto/buf.gen.rust.yaml | 11 - fairyring_contract/proto/buf.lock | 53 -- fairyring_contract/proto/buf.yaml | 27 - fairyring_contract/proto/pep.proto | 25 - fairyring_contract/src/contract.rs | 4 +- fairyring_contract/src/fairyring.common.rs | 76 -- .../src/fairyring.keyshare.module.rs | 10 - fairyring_contract/src/fairyring.keyshare.rs | 683 --------------- .../src/fairyring.keyshare.tonic.rs | 799 ------------------ .../src/fairyring.pep.module.rs | 10 - fairyring_contract/src/fairyring.pep.rs | 340 -------- fairyring_contract/src/fairyring.pep.tonic.rs | 581 ------------- fairyring_contract/src/lib.rs | 6 +- 15 files changed, 203 insertions(+), 2622 deletions(-) delete mode 100644 fairyring_contract/proto/buf.gen.rust.yaml delete mode 100644 fairyring_contract/proto/buf.lock delete mode 100644 fairyring_contract/proto/buf.yaml delete mode 100644 fairyring_contract/proto/pep.proto delete mode 100644 fairyring_contract/src/fairyring.common.rs delete mode 100644 fairyring_contract/src/fairyring.keyshare.module.rs delete mode 100644 fairyring_contract/src/fairyring.keyshare.rs delete mode 100644 fairyring_contract/src/fairyring.keyshare.tonic.rs delete mode 100644 fairyring_contract/src/fairyring.pep.module.rs delete mode 100644 fairyring_contract/src/fairyring.pep.rs delete mode 100644 fairyring_contract/src/fairyring.pep.tonic.rs diff --git a/fairyring_contract/Cargo.lock b/fairyring_contract/Cargo.lock index 4b43fdd1..0b0e163e 100644 --- a/fairyring_contract/Cargo.lock +++ b/fairyring_contract/Cargo.lock @@ -302,6 +302,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e31ea183f6ee62ac8b8a8cf7feddd766317adfb13ff469de57ce033efd6a790" +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -313,6 +319,9 @@ name = "bytes" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +dependencies = [ + "serde", +] [[package]] name = "cc" @@ -335,6 +344,18 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "cosmos-sdk-proto" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2f63ab112b8c8e7b8a29c891adc48f43145beb21c0bfbf562957072c1e0beb" +dependencies = [ + "prost", + "prost-types", + "tendermint-proto", + "tonic", +] + [[package]] name = "cosmwasm-core" version = "2.1.4" @@ -559,6 +580,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivative" version = "2.2.0" @@ -676,6 +706,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "fairblock-proto" +version = "0.1.0" +source = "git+https://github.com/Fairblock/fairblock-rust/?branch=contract-callback#3eb0f729a25389fdf68a0fba81aaa861c826d79a" +dependencies = [ + "cosmos-sdk-proto", + "prost", + "prost-types", + "tonic", +] + [[package]] name = "fairyring_contract" version = "0.1.0" @@ -684,11 +725,15 @@ dependencies = [ "cosmwasm-std", "cw-multi-test", "cw-storage-plus", + "fairblock-proto", + "getrandom", + "mio", "prost", "prost-types", "schemars", "serde", "thiserror", + "tokio", "tonic", ] @@ -708,6 +753,15 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "flex-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" +dependencies = [ + "paste", +] + [[package]] name = "fnv" version = "1.0.7" @@ -771,8 +825,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1000,6 +1056,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "k256" version = "0.13.4" @@ -1059,6 +1124,7 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", + "log", "wasi", "windows-sys", ] @@ -1073,6 +1139,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.46" @@ -1171,6 +1243,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -1444,6 +1522,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.210" @@ -1548,6 +1635,15 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + [[package]] name = "syn" version = "1.0.109" @@ -1582,6 +1678,22 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +[[package]] +name = "tendermint-proto" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed14abe3b0502a3afe21ca74ca5cdd6c7e8d326d982c26f98a394445eb31d6e" +dependencies = [ + "bytes", + "flex-error", + "prost", + "prost-types", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + [[package]] name = "thiserror" version = "1.0.64" @@ -1602,6 +1714,35 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tokio" version = "1.40.0" @@ -1824,6 +1965,61 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/fairyring_contract/Cargo.toml b/fairyring_contract/Cargo.toml index 24d350fb..64b63052 100644 --- a/fairyring_contract/Cargo.toml +++ b/fairyring_contract/Cargo.toml @@ -42,6 +42,10 @@ thiserror = "1.0" prost = "0.13.3" # Protobuf support prost-types = "0.13" tonic = { version = "0.12.3", features = ["prost", "tls"] } +fairblock-proto = { git = "https://github.com/Fairblock/fairblock-rust/", branch = "contract-callback" } +getrandom = { version = "0.2", features = ["js"] } +mio = "1.0.2" +tokio = "1.40.0" [dev-dependencies] cw-multi-test = "2.0.0" \ No newline at end of file diff --git a/fairyring_contract/proto/buf.gen.rust.yaml b/fairyring_contract/proto/buf.gen.rust.yaml deleted file mode 100644 index ffa7062c..00000000 --- a/fairyring_contract/proto/buf.gen.rust.yaml +++ /dev/null @@ -1,11 +0,0 @@ -version: v2 -plugins: - - remote: buf.build/community/neoeinstein-prost:v0.3.1 - out: ../fairblock-proto/src/prost/ - opt: - - extern_path=.cosmos=cosmos_sdk_proto::cosmos - - remote: buf.build/community/neoeinstein-tonic:v0.3.0 - out: ../fairblock-proto/src/prost/ - opt: - - no_server - - extern_path=.cosmos=cosmos_sdk_proto::cosmos \ No newline at end of file diff --git a/fairyring_contract/proto/buf.lock b/fairyring_contract/proto/buf.lock deleted file mode 100644 index 229e70e0..00000000 --- a/fairyring_contract/proto/buf.lock +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by buf. DO NOT EDIT. -version: v1 -deps: - - remote: buf.build - owner: cosmos - repository: cosmos-proto - commit: 04467658e59e44bbb22fe568206e1f70 - digest: shake256:73a640bd60e0c523b0f8237ff34eab67c45a38b64bbbde1d80224819d272dbf316ac183526bd245f994af6608b025f5130483d0133c5edd385531326b5990466 - - remote: buf.build - owner: cosmos - repository: cosmos-sdk - commit: 05419252bcc241ea8023acf1ed4cadc5 - digest: shake256:1e54a48c19a8b59d35e0a7efa76402939f515f2d8005df099856f24c37c20a52800308f025abb8cffcd014d437b49707388aaca4865d9d063d8f25d5d4eb77d5 - - remote: buf.build - owner: cosmos - repository: gogo-proto - commit: 88ef6483f90f478fb938c37dde52ece3 - digest: shake256:89c45df2aa11e0cff97b0d695436713db3d993d76792e9f8dc1ae90e6ab9a9bec55503d48ceedd6b86069ab07d3041b32001b2bfe0227fa725dd515ff381e5ba - - remote: buf.build - owner: cosmos - repository: ibc - commit: 41fbc441e4d645119d275150719c5441 - digest: shake256:a61d3e152909abddc91dcc1aec8ac997007bebd48a7921bc243681c708e6c9068f6484aa7ed4e6ff60101d3422c98744a4a5294bbda6aacdba07f1dfa4291020 - - remote: buf.build - owner: cosmos - repository: ics23 - commit: dc427cb4519143d8996361c045a29ad7 - digest: shake256:f6611c56170e2cb6354fa6e367a225fed7b8b0defca3252f05e842fe311be46997680ebf57d8644b52c1f2cca49b366ffe89ce5e8db5fd055a15259c88e4e41e - - remote: buf.build - owner: cosmos - repository: interchain-security - commit: 8eccf50752a5463a9c59dbe8fc9d043a - digest: shake256:6d581ed256c376984e479f5d1dd440263833b76226dc19db53deaff09d5be4bed71a05610630e053630e27890fd9492100779e0c87ed5963559583c4ab77f152 - - remote: buf.build - owner: cosmwasm - repository: wasmd - commit: 5af8ba5098c74f67b7e900e1c6c3dcdf - digest: shake256:e270738e4950538ca149674972f8f0a8243bb795c7c5d2b5807348fec5aae42ddb646827ef08dd200ed65a4be0ab450162d48f1f5d0dae9446696ccb286b90db - - remote: buf.build - owner: googleapis - repository: googleapis - commit: e7f8d366f5264595bcc4cd4139af9973 - digest: shake256:e5e5f1c12f82e028ea696faa43b4f9dc6258a6d1226282962a8c8b282e10946281d815884f574bd279ebd9cd7588629beb3db17b892af6c33b56f92f8f67f509 - - remote: buf.build - owner: protocolbuffers - repository: wellknowntypes - commit: d59b7d45e69d4e129a1b797e2766f067 - digest: shake256:e4bb315f5a90aace88fe39709c831eda8eb0ce66b4cf947065888100b9867c2eb9a0f61f6b8d73c51b1fcccdfe8611090f55ce5db1aee6901ec9b4e6d8fa8e52 - - remote: buf.build - owner: tendermint - repository: tendermint - commit: 33ed361a90514289beabf3189e1d7665 - digest: shake256:038267e06294714fd883610626554b04a127b576b4e253befb4206cb72d5d3c1eeccacd4b9ec8e3fb891f7c14e1cb0f770c077d2989638995b0a61c85afedb1d diff --git a/fairyring_contract/proto/buf.yaml b/fairyring_contract/proto/buf.yaml deleted file mode 100644 index 98b607a0..00000000 --- a/fairyring_contract/proto/buf.yaml +++ /dev/null @@ -1,27 +0,0 @@ -breaking: - use: - - FILE -deps: -- buf.build/protocolbuffers/wellknowntypes -- buf.build/cosmos/cosmos-sdk -- buf.build/cosmos/cosmos-proto -- buf.build/cosmos/gogo-proto -- buf.build/googleapis/googleapis -- buf.build/cosmos/ics23 -- buf.build/cosmos/interchain-security -- buf.build/cosmos/ibc -- buf.build/cosmwasm/wasmd -lint: - except: - - UNARY_RPC - - COMMENT_FIELD - - SERVICE_SUFFIX - - PACKAGE_VERSION_SUFFIX - - RPC_REQUEST_STANDARD_NAME - ignore: - - tendermint - use: - - DEFAULT - - COMMENTS - - FILE_LOWER_SNAKE_CASE -version: v1 diff --git a/fairyring_contract/proto/pep.proto b/fairyring_contract/proto/pep.proto deleted file mode 100644 index 3609f35a..00000000 --- a/fairyring_contract/proto/pep.proto +++ /dev/null @@ -1,25 +0,0 @@ -syntax = "proto3"; - -package fairyring.pep; - -import "google/api/annotations.proto"; -option go_package = "github.com/Fairblock/fairyring/x/pep/types"; - -// Query defines the gRPC querier service. -service Query { - // Queries a list of DecryptData items. - rpc DecryptData (QueryDecryptDataRequest) returns (QueryDecryptDataResponse) { - option (google.api.http).get = "/Fairblock/fairyring/pep/decrypt_data/{aggr_keyshare}/{encrypted_data}"; - - } -} - -message QueryDecryptDataRequest { - string pubkey = 1; - string aggr_keyshare = 2; - string encrypted_data = 3; -} - -message QueryDecryptDataResponse { - string decrypted_data = 1; -} \ No newline at end of file diff --git a/fairyring_contract/src/contract.rs b/fairyring_contract/src/contract.rs index cfba3024..76cd416e 100644 --- a/fairyring_contract/src/contract.rs +++ b/fairyring_contract/src/contract.rs @@ -1,7 +1,7 @@ // contract.rs use cosmwasm_std::{attr, entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; -use crate::fairyring::pep::query_client::QueryClient; // The generated gRPC client -use crate::fairyring::pep::QueryDecryptDataRequest; // Generated message types +use fairblock_proto::fairyring::pep::query_client::QueryClient; +use fairblock_proto::fairyring::pep::QueryDecryptDataRequest; use crate::msg::{ExecuteContractMsg, QueryMsg, QueryResponse, InstantiateMsg}; use crate::state::STORED_DATA; diff --git a/fairyring_contract/src/fairyring.common.rs b/fairyring_contract/src/fairyring.common.rs deleted file mode 100644 index 279f1e37..00000000 --- a/fairyring_contract/src/fairyring.common.rs +++ /dev/null @@ -1,76 +0,0 @@ -// @generated -/// RequestAggrKeyshare defines a struct for the data payload -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RequestAggrKeyshare { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(message, optional, tag="4")] - pub estimated_delay: ::core::option::Option<::prost_types::Duration>, - #[prost(oneof="request_aggr_keyshare::Id", tags="2, 3")] - pub id: ::core::option::Option, -} -/// Nested message and enum types in `RequestAggrKeyshare`. -pub mod request_aggr_keyshare { - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Id { - #[prost(string, tag="2")] - ProposalId(::prost::alloc::string::String), - #[prost(string, tag="3")] - RequestId(::prost::alloc::string::String), - } -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RequestAggrKeyshareResponse { - #[prost(string, tag="1")] - pub identity: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub pubkey: ::prost::alloc::string::String, -} -/// GetAggrKeyshare defines a struct for the data payload -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GetAggrKeyshare { - #[prost(string, tag="3")] - pub identity: ::prost::alloc::string::String, - #[prost(oneof="get_aggr_keyshare::Id", tags="1, 2")] - pub id: ::core::option::Option, -} -/// Nested message and enum types in `GetAggrKeyshare`. -pub mod get_aggr_keyshare { - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Id { - #[prost(string, tag="1")] - ProposalId(::prost::alloc::string::String), - #[prost(string, tag="2")] - RequestId(::prost::alloc::string::String), - } -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GetAggrKeyshareResponse { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActivePublicKey { - #[prost(string, tag="1")] - pub public_key: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub creator: ::prost::alloc::string::String, - #[prost(uint64, tag="3")] - pub expiry: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueuedPublicKey { - #[prost(string, tag="1")] - pub public_key: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub creator: ::prost::alloc::string::String, - #[prost(uint64, tag="3")] - pub expiry: u64, -} -// @@protoc_insertion_point(module) diff --git a/fairyring_contract/src/fairyring.keyshare.module.rs b/fairyring_contract/src/fairyring.keyshare.module.rs deleted file mode 100644 index e4db05ff..00000000 --- a/fairyring_contract/src/fairyring.keyshare.module.rs +++ /dev/null @@ -1,10 +0,0 @@ -// @generated -/// Module is the config object for the module. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Module { - /// authority defines the custom module authority. If not set, defaults to the governance module. - #[prost(string, tag="1")] - pub authority: ::prost::alloc::string::String, -} -// @@protoc_insertion_point(module) diff --git a/fairyring_contract/src/fairyring.keyshare.rs b/fairyring_contract/src/fairyring.keyshare.rs deleted file mode 100644 index d070e0f2..00000000 --- a/fairyring_contract/src/fairyring.keyshare.rs +++ /dev/null @@ -1,683 +0,0 @@ -// @generated -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct AggregatedKeyShare { - #[prost(uint64, tag="1")] - pub height: u64, - #[prost(string, tag="2")] - pub data: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct AuthorizedAddress { - #[prost(string, tag="1")] - pub target: ::prost::alloc::string::String, - #[prost(bool, tag="2")] - pub is_authorized: bool, - #[prost(string, tag="3")] - pub authorized_by: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Commitments { - #[prost(string, repeated, tag="1")] - pub commitments: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GeneralKeyShare { - #[prost(string, tag="1")] - pub validator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub id_type: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub id_value: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub key_share: ::prost::alloc::string::String, - #[prost(uint64, tag="5")] - pub key_share_index: u64, - #[prost(uint64, tag="6")] - pub received_timestamp: u64, - #[prost(uint64, tag="7")] - pub received_block_height: u64, -} -/// Params defines the parameters for the module. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Params { - #[prost(uint64, tag="1")] - pub key_expiry: u64, - #[prost(uint64, tag="2")] - pub minimum_bonded: u64, - #[prost(uint64, tag="3")] - pub max_idled_block: u64, - #[prost(string, repeated, tag="4")] - pub trusted_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(bytes="vec", tag="5")] - pub slash_fraction_no_keyshare: ::prost::alloc::vec::Vec, - #[prost(bytes="vec", tag="6")] - pub slash_fraction_wrong_keyshare: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ValidatorSet { - #[prost(string, tag="1")] - pub index: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub validator: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub cons_addr: ::prost::alloc::string::String, - #[prost(bool, tag="4")] - pub is_active: bool, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct KeyShare { - #[prost(string, tag="1")] - pub validator: ::prost::alloc::string::String, - #[prost(uint64, tag="2")] - pub block_height: u64, - #[prost(string, tag="3")] - pub key_share: ::prost::alloc::string::String, - #[prost(uint64, tag="4")] - pub key_share_index: u64, - #[prost(uint64, tag="5")] - pub received_timestamp: u64, - #[prost(uint64, tag="6")] - pub received_block_height: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct EncryptedKeyShare { - #[prost(string, tag="1")] - pub data: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub validator: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActivePubKey { - #[prost(string, tag="1")] - pub public_key: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub creator: ::prost::alloc::string::String, - #[prost(uint64, tag="3")] - pub expiry: u64, - #[prost(uint64, tag="4")] - pub number_of_validators: u64, - #[prost(message, repeated, tag="5")] - pub encrypted_key_shares: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueuedPubKey { - #[prost(string, tag="1")] - pub public_key: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub creator: ::prost::alloc::string::String, - #[prost(uint64, tag="3")] - pub expiry: u64, - #[prost(uint64, tag="4")] - pub number_of_validators: u64, - #[prost(message, repeated, tag="5")] - pub encrypted_key_shares: ::prost::alloc::vec::Vec, -} -/// GenesisState defines the keyshare module's genesis state. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GenesisState { - /// params defines all the parameters of the module. - #[prost(message, optional, tag="1")] - pub params: ::core::option::Option, - #[prost(string, tag="2")] - pub port_id: ::prost::alloc::string::String, - #[prost(message, repeated, tag="3")] - pub validator_set_list: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="4")] - pub key_share_list: ::prost::alloc::vec::Vec, - /// this line is used by starport scaffolding # genesis/proto/state - #[prost(message, repeated, tag="5")] - pub aggregated_key_share_list: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="6")] - pub active_pub_key: ::core::option::Option, - #[prost(message, optional, tag="7")] - pub queued_pub_key: ::core::option::Option, - #[prost(message, repeated, tag="8")] - pub authorized_address_list: ::prost::alloc::vec::Vec, - #[prost(uint64, tag="9")] - pub request_count: u64, - #[prost(message, repeated, tag="10")] - pub general_key_share_list: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct KeysharePacketData { - #[prost(oneof="keyshare_packet_data::Packet", tags="1, 2, 3, 4, 5")] - pub packet: ::core::option::Option, -} -/// Nested message and enum types in `KeysharePacketData`. -pub mod keyshare_packet_data { - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Packet { - #[prost(message, tag="1")] - NoData(super::NoData), - #[prost(message, tag="2")] - RequestAggrKeysharePacket(super::RequestAggrKeysharePacketData), - #[prost(message, tag="3")] - GetAggrKeysharePacket(super::GetAggrKeysharePacketData), - #[prost(message, tag="4")] - AggrKeyshareDataPacket(super::AggrKeyshareDataPacketData), - #[prost(message, tag="5")] - CurrentKeysPacket(super::CurrentKeysPacketData), - } -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct NoData { -} -/// RequestAggrKeysharePacketData defines a struct for the packet payload -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RequestAggrKeysharePacketData { - #[prost(string, tag="1")] - pub requester: ::prost::alloc::string::String, - #[prost(message, optional, tag="4")] - pub estimated_delay: ::core::option::Option<::prost_types::Duration>, - #[prost(oneof="request_aggr_keyshare_packet_data::Id", tags="2, 3")] - pub id: ::core::option::Option, -} -/// Nested message and enum types in `RequestAggrKeysharePacketData`. -pub mod request_aggr_keyshare_packet_data { - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Id { - #[prost(string, tag="2")] - ProposalId(::prost::alloc::string::String), - #[prost(string, tag="3")] - RequestId(::prost::alloc::string::String), - } -} -/// RequestAggrKeysharePacketAck defines a struct for the packet acknowledgment -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RequestAggrKeysharePacketAck { - #[prost(string, tag="1")] - pub identity: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub pubkey: ::prost::alloc::string::String, -} -/// GetAggrKeysharePacketData defines a struct for the packet payload -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GetAggrKeysharePacketData { - #[prost(string, tag="1")] - pub identity: ::prost::alloc::string::String, -} -/// GetAggrKeysharePacketAck defines a struct for the packet acknowledgment -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GetAggrKeysharePacketAck { -} -/// AggrKeyshareDataPacketData defines a struct for the packet payload -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct AggrKeyshareDataPacketData { - #[prost(string, tag="1")] - pub identity: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub pubkey: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub aggr_keyshare: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub aggr_height: ::prost::alloc::string::String, - /// used for private governance - #[prost(string, tag="5")] - pub proposal_id: ::prost::alloc::string::String, - /// might be useful to destination chains to sort out the response - #[prost(string, tag="6")] - pub request_id: ::prost::alloc::string::String, - #[prost(uint64, tag="7")] - pub retries: u64, -} -/// AggrKeyshareDataPacketAck defines a struct for the packet acknowledgment -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct AggrKeyshareDataPacketAck { -} -/// CurrentKeysPacketData defines a struct for the packet payload -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CurrentKeysPacketData { -} -/// CurrentKeysPacketAck defines a struct for the packet acknowledgment -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CurrentKeysPacketAck { - #[prost(message, optional, tag="1")] - pub active_key: ::core::option::Option, - #[prost(message, optional, tag="2")] - pub queued_key: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryVerifiableRandomnessQuery { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryVerifiableRandomnessResponse { - #[prost(string, tag="1")] - pub randomness: ::prost::alloc::string::String, - #[prost(uint64, tag="2")] - pub round: u64, -} -/// QueryParamsRequest is request type for the Query/Params RPC method. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryParamsRequest { -} -/// QueryParamsResponse is response type for the Query/Params RPC method. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryParamsResponse { - /// params holds all the parameters of this module. - #[prost(message, optional, tag="1")] - pub params: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryCommitmentsRequest { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryCommitmentsResponse { - #[prost(message, optional, tag="1")] - pub active_commitments: ::core::option::Option, - #[prost(message, optional, tag="2")] - pub queued_commitments: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetValidatorSetRequest { - #[prost(string, tag="1")] - pub index: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetValidatorSetResponse { - #[prost(message, optional, tag="1")] - pub validator_set: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllValidatorSetRequest { - #[prost(message, optional, tag="1")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllValidatorSetResponse { - #[prost(message, repeated, tag="1")] - pub validator_set: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="2")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetKeyShareRequest { - #[prost(string, tag="1")] - pub validator: ::prost::alloc::string::String, - #[prost(uint64, tag="2")] - pub block_height: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetKeyShareResponse { - #[prost(message, optional, tag="1")] - pub key_share: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllKeyShareRequest { - #[prost(message, optional, tag="1")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllKeyShareResponse { - #[prost(message, repeated, tag="1")] - pub key_share: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="2")] - pub pagination: ::core::option::Option, -} -/// this line is used by starport scaffolding # 3 -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetAggregatedKeyShareRequest { - #[prost(uint64, tag="1")] - pub height: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetAggregatedKeyShareResponse { - #[prost(message, optional, tag="1")] - pub aggregated_key_share: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllAggregatedKeyShareRequest { - #[prost(message, optional, tag="1")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllAggregatedKeyShareResponse { - #[prost(message, repeated, tag="1")] - pub aggregated_key_share: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="2")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryPubKeyRequest { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryPubKeyResponse { - #[prost(message, optional, tag="1")] - pub active_pub_key: ::core::option::Option, - #[prost(message, optional, tag="2")] - pub queued_pub_key: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetAuthorizedAddressRequest { - #[prost(string, tag="1")] - pub target: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetAuthorizedAddressResponse { - #[prost(message, optional, tag="1")] - pub authorized_address: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllAuthorizedAddressRequest { - #[prost(message, optional, tag="1")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllAuthorizedAddressResponse { - #[prost(message, repeated, tag="1")] - pub authorized_address: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="2")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetGeneralKeyShareRequest { - #[prost(string, tag="1")] - pub validator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub id_type: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub id_value: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetGeneralKeyShareResponse { - #[prost(message, optional, tag="1")] - pub general_key_share: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllGeneralKeyShareRequest { - #[prost(message, optional, tag="1")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllGeneralKeyShareResponse { - #[prost(message, repeated, tag="1")] - pub general_key_share: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="2")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct KeyShareRequest { - #[prost(string, tag="1")] - pub identity: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub pubkey: ::prost::alloc::string::String, - /// Used only when the request is made via IBC - #[prost(message, optional, tag="3")] - pub ibc_info: ::core::option::Option, - /// Used only when the request is made via IBC - #[prost(message, optional, tag="4")] - pub counterparty: ::core::option::Option, - #[prost(string, tag="5")] - pub aggr_keyshare: ::prost::alloc::string::String, - /// This is only used when the request is for private governance - #[prost(string, tag="6")] - pub proposal_id: ::prost::alloc::string::String, - /// might be useful to destination chains to sort out the response - #[prost(string, tag="7")] - pub request_id: ::prost::alloc::string::String, - #[prost(bool, tag="8")] - pub sent: bool, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct IbcInfo { - #[prost(string, tag="1")] - pub client_id: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub connection_id: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub channel_id: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub port_id: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CounterPartyIbcInfo { - #[prost(string, tag="1")] - pub client_id: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub connection_id: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub channel_id: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub port_id: ::prost::alloc::string::String, -} -/// MsgUpdateParams is the Msg/UpdateParams request type. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgUpdateParams { - /// authority is the address that controls the module (defaults to x/gov unless overwritten). - #[prost(string, tag="1")] - pub authority: ::prost::alloc::string::String, - // params defines the module parameters to update. - - /// NOTE: All parameters must be supplied. - #[prost(message, optional, tag="2")] - pub params: ::core::option::Option, -} -/// MsgUpdateParamsResponse defines the response structure for executing a -/// MsgUpdateParams message. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgUpdateParamsResponse { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgRegisterValidator { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgRegisterValidatorResponse { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgDeRegisterValidator { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgDeRegisterValidatorResponse { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgSendKeyshare { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub message: ::prost::alloc::string::String, - #[prost(uint64, tag="3")] - pub key_share_index: u64, - #[prost(uint64, tag="4")] - pub block_height: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgSendKeyshareResponse { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub keyshare: ::prost::alloc::string::String, - #[prost(uint64, tag="3")] - pub keyshare_index: u64, - #[prost(uint64, tag="4")] - pub block_height: u64, - #[prost(uint64, tag="5")] - pub received_block_height: u64, - #[prost(bool, tag="6")] - pub success: bool, - #[prost(string, tag="7")] - pub error_message: ::prost::alloc::string::String, -} -/// this line is used by starport scaffolding # proto/tx/message -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgCreateLatestPubKey { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub public_key: ::prost::alloc::string::String, - #[prost(string, repeated, tag="3")] - pub commitments: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(uint64, tag="4")] - pub number_of_validators: u64, - #[prost(message, repeated, tag="5")] - pub encrypted_key_shares: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgCreateLatestPubKeyResponse { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgOverrideLatestPubKey { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub public_key: ::prost::alloc::string::String, - #[prost(string, repeated, tag="3")] - pub commitments: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(uint64, tag="4")] - pub number_of_validators: u64, - #[prost(message, repeated, tag="5")] - pub encrypted_key_shares: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgOverrideLatestPubKeyResponse { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgCreateAuthorizedAddress { - #[prost(string, tag="1")] - pub target: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub creator: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgCreateAuthorizedAddressResponse { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgUpdateAuthorizedAddress { - #[prost(string, tag="1")] - pub target: ::prost::alloc::string::String, - #[prost(bool, tag="2")] - pub is_authorized: bool, - #[prost(string, tag="3")] - pub creator: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgUpdateAuthorizedAddressResponse { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgDeleteAuthorizedAddress { - #[prost(string, tag="1")] - pub target: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub creator: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgDeleteAuthorizedAddressResponse { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgCreateGeneralKeyShare { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub id_type: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub id_value: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub key_share: ::prost::alloc::string::String, - #[prost(uint64, tag="5")] - pub key_share_index: u64, - #[prost(uint64, tag="6")] - pub received_timestamp: u64, - #[prost(uint64, tag="7")] - pub received_block_height: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgCreateGeneralKeyShareResponse { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub id_type: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub id_value: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub key_share: ::prost::alloc::string::String, - #[prost(uint64, tag="5")] - pub key_share_index: u64, - #[prost(uint64, tag="6")] - pub received_block_height: u64, - #[prost(bool, tag="7")] - pub success: bool, - #[prost(string, tag="8")] - pub error_message: ::prost::alloc::string::String, -} -include!("fairyring.keyshare.tonic.rs"); -// @@protoc_insertion_point(module) \ No newline at end of file diff --git a/fairyring_contract/src/fairyring.keyshare.tonic.rs b/fairyring_contract/src/fairyring.keyshare.tonic.rs deleted file mode 100644 index 7aff25c0..00000000 --- a/fairyring_contract/src/fairyring.keyshare.tonic.rs +++ /dev/null @@ -1,799 +0,0 @@ -// @generated -/// Generated client implementations. -pub mod query_client { - #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - #[derive(Debug, Clone)] - pub struct QueryClient { - inner: tonic::client::Grpc, - } - impl QueryClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl QueryClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + Send + 'static, - ::Error: Into + Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> QueryClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + Send + Sync, - { - QueryClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - pub async fn params( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/Params", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Query", "Params")); - self.inner.unary(req, path, codec).await - } - pub async fn commitments( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/Commitments", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Query", "Commitments")); - self.inner.unary(req, path, codec).await - } - pub async fn validator_set( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/ValidatorSet", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Query", "ValidatorSet")); - self.inner.unary(req, path, codec).await - } - pub async fn validator_set_all( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/ValidatorSetAll", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Query", "ValidatorSetAll")); - self.inner.unary(req, path, codec).await - } - pub async fn key_share( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/KeyShare", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Query", "KeyShare")); - self.inner.unary(req, path, codec).await - } - pub async fn key_share_all( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/KeyShareAll", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Query", "KeyShareAll")); - self.inner.unary(req, path, codec).await - } - pub async fn aggregated_key_share( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/AggregatedKeyShare", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Query", "AggregatedKeyShare"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn aggregated_key_share_all( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/AggregatedKeyShareAll", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Query", "AggregatedKeyShareAll"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn pub_key( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/PubKey", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Query", "PubKey")); - self.inner.unary(req, path, codec).await - } - pub async fn authorized_address( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/AuthorizedAddress", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Query", "AuthorizedAddress"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn authorized_address_all( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/AuthorizedAddressAll", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Query", "AuthorizedAddressAll"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn general_key_share( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/GeneralKeyShare", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Query", "GeneralKeyShare")); - self.inner.unary(req, path, codec).await - } - pub async fn general_key_share_all( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/GeneralKeyShareAll", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Query", "GeneralKeyShareAll"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn verifiable_randomness( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Query/VerifiableRandomness", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Query", "VerifiableRandomness"), - ); - self.inner.unary(req, path, codec).await - } - } -} -/// Generated client implementations. -pub mod msg_client { - #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - #[derive(Debug, Clone)] - pub struct MsgClient { - inner: tonic::client::Grpc, - } - impl MsgClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl MsgClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + Send + 'static, - ::Error: Into + Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> MsgClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + Send + Sync, - { - MsgClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - pub async fn update_params( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/UpdateParams", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Msg", "UpdateParams")); - self.inner.unary(req, path, codec).await - } - pub async fn register_validator( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/RegisterValidator", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Msg", "RegisterValidator")); - self.inner.unary(req, path, codec).await - } - pub async fn de_register_validator( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/DeRegisterValidator", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Msg", "DeRegisterValidator"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn send_keyshare( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/SendKeyshare", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Msg", "SendKeyshare")); - self.inner.unary(req, path, codec).await - } - pub async fn create_latest_pub_key( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/CreateLatestPubKey", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.keyshare.Msg", "CreateLatestPubKey")); - self.inner.unary(req, path, codec).await - } - pub async fn override_latest_pub_key( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/OverrideLatestPubKey", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Msg", "OverrideLatestPubKey"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn create_authorized_address( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/CreateAuthorizedAddress", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Msg", "CreateAuthorizedAddress"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn update_authorized_address( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/UpdateAuthorizedAddress", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Msg", "UpdateAuthorizedAddress"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn delete_authorized_address( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/DeleteAuthorizedAddress", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Msg", "DeleteAuthorizedAddress"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn create_general_key_share( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.keyshare.Msg/CreateGeneralKeyShare", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.keyshare.Msg", "CreateGeneralKeyShare"), - ); - self.inner.unary(req, path, codec).await - } - } -} diff --git a/fairyring_contract/src/fairyring.pep.module.rs b/fairyring_contract/src/fairyring.pep.module.rs deleted file mode 100644 index e4db05ff..00000000 --- a/fairyring_contract/src/fairyring.pep.module.rs +++ /dev/null @@ -1,10 +0,0 @@ -// @generated -/// Module is the config object for the module. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Module { - /// authority defines the custom module authority. If not set, defaults to the governance module. - #[prost(string, tag="1")] - pub authority: ::prost::alloc::string::String, -} -// @@protoc_insertion_point(module) diff --git a/fairyring_contract/src/fairyring.pep.rs b/fairyring_contract/src/fairyring.pep.rs deleted file mode 100644 index 4f73a46a..00000000 --- a/fairyring_contract/src/fairyring.pep.rs +++ /dev/null @@ -1,340 +0,0 @@ -// @generated -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct AggregatedKeyShare { - #[prost(uint64, tag="1")] - pub height: u64, - #[prost(string, tag="2")] - pub data: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub creator: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct EncryptedTx { - #[prost(uint64, tag="1")] - pub target_height: u64, - #[prost(uint64, tag="2")] - pub index: u64, - #[prost(string, tag="3")] - pub data: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub creator: ::prost::alloc::string::String, - #[prost(message, optional, tag="5")] - pub charged_gas: ::core::option::Option, - #[prost(uint64, tag="6")] - pub processed_at_chain_height: u64, - #[prost(bool, tag="7")] - pub expired: bool, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct EncryptedTxArray { - #[prost(message, repeated, tag="1")] - pub encrypted_tx: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GeneralEncryptedTx { - #[prost(string, tag="1")] - pub identity: ::prost::alloc::string::String, - #[prost(uint64, tag="2")] - pub index: u64, - #[prost(string, tag="3")] - pub data: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub creator: ::prost::alloc::string::String, - #[prost(message, optional, tag="5")] - pub charged_gas: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GeneralEncryptedTxArray { - #[prost(message, repeated, tag="1")] - pub encrypted_tx: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GenEncTxExecutionQueue { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub request_id: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub identity: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub pubkey: ::prost::alloc::string::String, - #[prost(message, optional, tag="5")] - pub tx_list: ::core::option::Option, - #[prost(string, tag="6")] - pub aggr_keyshare: ::prost::alloc::string::String, -} -/// Params defines the parameters for the module. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Params { - #[prost(string, tag="1")] - pub keyshare_channel_id: ::prost::alloc::string::String, - #[prost(bool, tag="2")] - pub is_source_chain: bool, - #[prost(message, repeated, tag="3")] - pub trusted_counter_parties: ::prost::alloc::vec::Vec, - #[prost(string, repeated, tag="4")] - pub trusted_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(message, optional, tag="5")] - pub min_gas_price: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TrustedCounterParty { - #[prost(string, tag="1")] - pub client_id: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub connection_id: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub channel_id: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PepNonce { - #[prost(string, tag="1")] - pub address: ::prost::alloc::string::String, - #[prost(uint64, tag="2")] - pub nonce: u64, -} -/// GenesisState defines the pep module's genesis state. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GenesisState { - /// params defines all the parameters of the module. - #[prost(message, optional, tag="1")] - pub params: ::core::option::Option, - #[prost(string, tag="2")] - pub port_id: ::prost::alloc::string::String, - #[prost(message, repeated, tag="3")] - pub encrypted_tx_array: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="4")] - pub pep_nonce_list: ::prost::alloc::vec::Vec, - /// this line is used by starport scaffolding # genesis/proto/state - #[prost(message, repeated, tag="6")] - pub aggregated_key_share_list: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="7")] - pub active_pub_key: ::core::option::Option, - #[prost(message, optional, tag="8")] - pub queued_pub_key: ::core::option::Option, - #[prost(uint64, tag="9")] - pub request_count: u64, -} -/// QueryParamsRequest is request type for the Query/Params RPC method. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryParamsRequest { -} -/// QueryParamsResponse is response type for the Query/Params RPC method. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryParamsResponse { - /// params holds all the parameters of this module. - #[prost(message, optional, tag="1")] - pub params: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryKeyshareRequest { - #[prost(string, tag="1")] - pub req_id: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryKeyshareResponse { - #[prost(message, optional, tag="1")] - pub keyshare: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllKeyshareRequest { - #[prost(message, optional, tag="1")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllKeyshareResponse { - #[prost(message, repeated, tag="1")] - pub keyshares: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="2")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetEncryptedTxRequest { - #[prost(uint64, tag="1")] - pub target_height: u64, - #[prost(uint64, tag="2")] - pub index: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetEncryptedTxResponse { - #[prost(message, optional, tag="1")] - pub encrypted_tx: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllEncryptedTxRequest { - #[prost(message, optional, tag="1")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllEncryptedTxResponse { - #[prost(message, repeated, tag="1")] - pub encrypted_tx_array: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="2")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllEncryptedTxFromHeightRequest { - #[prost(uint64, tag="1")] - pub target_height: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllEncryptedTxFromHeightResponse { - #[prost(message, optional, tag="1")] - pub encrypted_tx_array: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryLatestHeightRequest { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryLatestHeightResponse { - #[prost(uint64, tag="1")] - pub height: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetPepNonceRequest { - #[prost(string, tag="1")] - pub address: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryGetPepNonceResponse { - #[prost(message, optional, tag="1")] - pub pep_nonce: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllPepNonceRequest { - #[prost(message, optional, tag="1")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryAllPepNonceResponse { - #[prost(message, repeated, tag="1")] - pub pep_nonce: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="2")] - pub pagination: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryPubKeyRequest { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryPubKeyResponse { - #[prost(message, optional, tag="1")] - pub active_pub_key: ::core::option::Option, - #[prost(message, optional, tag="2")] - pub queued_pub_key: ::core::option::Option, -} -/// MsgUpdateParams is the Msg/UpdateParams request type. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgUpdateParams { - /// authority is the address that controls the module (defaults to x/gov unless overwritten). - #[prost(string, tag="1")] - pub authority: ::prost::alloc::string::String, - /// params defines the module parameters to update. - /// - /// NOTE: All parameters must be supplied. - #[prost(message, optional, tag="2")] - pub params: ::core::option::Option, -} -/// MsgUpdateParamsResponse defines the response structure for executing a -/// MsgUpdateParams message. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgUpdateParamsResponse { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgSubmitEncryptedTx { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub data: ::prost::alloc::string::String, - #[prost(uint64, tag="3")] - pub target_block_height: u64, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgSubmitGeneralEncryptedTx { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub data: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub req_id: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgSubmitEncryptedTxResponse { -} -/// this line is used by starport scaffolding # proto/tx/message -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgCreateAggregatedKeyShare { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(uint64, tag="2")] - pub height: u64, - #[prost(string, tag="3")] - pub data: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgCreateAggregatedKeyShareResponse { -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgRequestGeneralKeyshare { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(message, optional, tag="2")] - pub estimated_delay: ::core::option::Option<::prost_types::Duration>, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgRequestGeneralKeyshareResponse { - #[prost(string, tag="1")] - pub req_id: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgGetGeneralKeyshare { - #[prost(string, tag="1")] - pub creator: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub req_id: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MsgGetGeneralKeyshareResponse { -} -include!("fairyring.pep.tonic.rs"); -// @@protoc_insertion_point(module) \ No newline at end of file diff --git a/fairyring_contract/src/fairyring.pep.tonic.rs b/fairyring_contract/src/fairyring.pep.tonic.rs deleted file mode 100644 index e33bd013..00000000 --- a/fairyring_contract/src/fairyring.pep.tonic.rs +++ /dev/null @@ -1,581 +0,0 @@ -// @generated -/// Generated client implementations. -pub mod query_client { - #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - #[derive(Debug, Clone)] - pub struct QueryClient { - inner: tonic::client::Grpc, - } - impl QueryClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl QueryClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + Send + 'static, - ::Error: Into + Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> QueryClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + Send + Sync, - { - QueryClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - pub async fn params( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/Params", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Query", "Params")); - self.inner.unary(req, path, codec).await - } - pub async fn encrypted_tx( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/EncryptedTx", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Query", "EncryptedTx")); - self.inner.unary(req, path, codec).await - } - pub async fn encrypted_tx_all( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/EncryptedTxAll", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Query", "EncryptedTxAll")); - self.inner.unary(req, path, codec).await - } - pub async fn encrypted_tx_all_from_height( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/EncryptedTxAllFromHeight", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.pep.Query", "EncryptedTxAllFromHeight"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn latest_height( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/LatestHeight", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Query", "LatestHeight")); - self.inner.unary(req, path, codec).await - } - pub async fn pep_nonce( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/PepNonce", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Query", "PepNonce")); - self.inner.unary(req, path, codec).await - } - pub async fn pep_nonce_all( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/PepNonceAll", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Query", "PepNonceAll")); - self.inner.unary(req, path, codec).await - } - pub async fn pub_key( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/PubKey", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Query", "PubKey")); - self.inner.unary(req, path, codec).await - } - pub async fn keyshare_req( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/KeyshareReq", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Query", "KeyshareReq")); - self.inner.unary(req, path, codec).await - } - pub async fn keyshare_req_all( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Query/KeyshareReqAll", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Query", "KeyshareReqAll")); - self.inner.unary(req, path, codec).await - } - } -} -/// Generated client implementations. -pub mod msg_client { - #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] - use tonic::codegen::*; - use tonic::codegen::http::Uri; - #[derive(Debug, Clone)] - pub struct MsgClient { - inner: tonic::client::Grpc, - } - impl MsgClient { - /// Attempt to create a new client by connecting to a given endpoint. - pub async fn connect(dst: D) -> Result - where - D: TryInto, - D::Error: Into, - { - let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; - Ok(Self::new(conn)) - } - } - impl MsgClient - where - T: tonic::client::GrpcService, - T::Error: Into, - T::ResponseBody: Body + Send + 'static, - ::Error: Into + Send, - { - pub fn new(inner: T) -> Self { - let inner = tonic::client::Grpc::new(inner); - Self { inner } - } - pub fn with_origin(inner: T, origin: Uri) -> Self { - let inner = tonic::client::Grpc::with_origin(inner, origin); - Self { inner } - } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> MsgClient> - where - F: tonic::service::Interceptor, - T::ResponseBody: Default, - T: tonic::codegen::Service< - http::Request, - Response = http::Response< - >::ResponseBody, - >, - >, - , - >>::Error: Into + Send + Sync, - { - MsgClient::new(InterceptedService::new(inner, interceptor)) - } - /// Compress requests with the given encoding. - /// - /// This requires the server to support it otherwise it might respond with an - /// error. - #[must_use] - pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.send_compressed(encoding); - self - } - /// Enable decompressing responses. - #[must_use] - pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { - self.inner = self.inner.accept_compressed(encoding); - self - } - /// Limits the maximum size of a decoded message. - /// - /// Default: `4MB` - #[must_use] - pub fn max_decoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_decoding_message_size(limit); - self - } - /// Limits the maximum size of an encoded message. - /// - /// Default: `usize::MAX` - #[must_use] - pub fn max_encoding_message_size(mut self, limit: usize) -> Self { - self.inner = self.inner.max_encoding_message_size(limit); - self - } - pub async fn update_params( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Msg/UpdateParams", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Msg", "UpdateParams")); - self.inner.unary(req, path, codec).await - } - pub async fn submit_encrypted_tx( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Msg/SubmitEncryptedTx", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Msg", "SubmitEncryptedTx")); - self.inner.unary(req, path, codec).await - } - pub async fn submit_general_encrypted_tx( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Msg/SubmitGeneralEncryptedTx", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.pep.Msg", "SubmitGeneralEncryptedTx"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn create_aggregated_key_share( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Msg/CreateAggregatedKeyShare", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("fairyring.pep.Msg", "CreateAggregatedKeyShare"), - ); - self.inner.unary(req, path, codec).await - } - pub async fn request_general_keyshare( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Msg/RequestGeneralKeyshare", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Msg", "RequestGeneralKeyshare")); - self.inner.unary(req, path, codec).await - } - pub async fn get_general_keyshare( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, - format!("Service was not ready: {}", e.into()), - ) - })?; - let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/fairyring.pep.Msg/GetGeneralKeyshare", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("fairyring.pep.Msg", "GetGeneralKeyshare")); - self.inner.unary(req, path, codec).await - } - } -} diff --git a/fairyring_contract/src/lib.rs b/fairyring_contract/src/lib.rs index b3ee57a3..94c37d1c 100644 --- a/fairyring_contract/src/lib.rs +++ b/fairyring_contract/src/lib.rs @@ -2,11 +2,7 @@ pub mod contract; pub mod msg; pub mod state; pub mod error; -pub mod fairyring{ - pub mod pep { - include!("fairyring.pep.rs"); - } -} + // use cosmwasm_std::{entry_point, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; From 866df2043af14aceffe99ebd591b7262d86162a2 Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Mon, 30 Sep 2024 21:40:11 -0400 Subject: [PATCH 16/41] Add remaining keyshare module tests --- go.mod | 3 +- go.sum | 7 + testutil/keeper/keyshare.go | 80 +++++- testutil/random/pubkey.go | 104 ++++++++ testutil/shares/derive.go | 38 +++ .../aggregated_key_share_request_test.go | 6 +- .../keeper/aggregated_key_share_test.go | 6 +- x/keyshare/keeper/authorized_address_test.go | 6 +- x/keyshare/keeper/commitments_test.go | 8 +- x/keyshare/keeper/general_key_share_test.go | 6 +- x/keyshare/keeper/key_share_test.go | 6 +- .../keeper/last_submitted_height_test.go | 2 +- .../keeper/msg_authorized_address_test.go | 165 ++++++++++++ .../msg_create_general_key_share_test.go | 240 ++++++++++++++++++ x/keyshare/keeper/msg_create_pub_key_test.go | 84 ++++++ .../keeper/msg_deregister_validator_test.go | 56 ++++ .../keeper/msg_override_pub_key_test.go | 70 +++++ .../keeper/msg_register_validator_test.go | 77 ++++++ x/keyshare/keeper/msg_send_key_share_test.go | 128 ++++++++++ x/keyshare/keeper/msg_server_test.go | 2 +- x/keyshare/keeper/params_test.go | 2 +- x/keyshare/keeper/pub_key_test.go | 8 +- .../keeper/query_aggregated_key_share_test.go | 6 +- .../keeper/query_authorized_address_test.go | 6 +- x/keyshare/keeper/query_commitments_test.go | 2 +- .../keeper/query_general_key_share_test.go | 6 +- x/keyshare/keeper/query_key_share_test.go | 6 +- x/keyshare/keeper/query_params_test.go | 50 +++- x/keyshare/keeper/query_pub_key_test.go | 51 ++++ x/keyshare/keeper/query_validator_set_test.go | 172 +++++++++++++ .../query_verifiable_randomness_test.go | 103 ++++++++ x/keyshare/keeper/validator_set_test.go | 6 +- 32 files changed, 1450 insertions(+), 62 deletions(-) create mode 100644 testutil/random/pubkey.go create mode 100644 testutil/shares/derive.go create mode 100644 x/keyshare/keeper/msg_authorized_address_test.go create mode 100644 x/keyshare/keeper/msg_create_general_key_share_test.go create mode 100644 x/keyshare/keeper/msg_create_pub_key_test.go create mode 100644 x/keyshare/keeper/msg_deregister_validator_test.go create mode 100644 x/keyshare/keeper/msg_override_pub_key_test.go create mode 100644 x/keyshare/keeper/msg_register_validator_test.go create mode 100644 x/keyshare/keeper/msg_send_key_share_test.go create mode 100644 x/keyshare/keeper/query_pub_key_test.go create mode 100644 x/keyshare/keeper/query_validator_set_test.go create mode 100644 x/keyshare/keeper/query_verifiable_randomness_test.go diff --git a/go.mod b/go.mod index 24477033..dab78080 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,7 @@ require ( github.com/cosmos/ibc-go/modules/capability v1.0.0 github.com/cosmos/ibc-go/v8 v8.2.1 github.com/cosmos/interchain-security/v3 v3.2.0-consumer-rc0.0.20231123140529-1819e73f6197 + github.com/decred/dcrd/dcrec/secp256k1 v1.0.4 github.com/drand/kyber v1.2.0 github.com/drand/kyber-bls12381 v0.3.1 github.com/golang/protobuf v1.5.4 @@ -111,6 +112,7 @@ require ( github.com/creachadair/tomledit v0.0.25 // indirect github.com/danieljoos/wincred v1.2.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect @@ -225,7 +227,6 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect - github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect diff --git a/go.sum b/go.sum index adcb708d..85ea718f 100644 --- a/go.sum +++ b/go.sum @@ -421,8 +421,15 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU= +github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1 v1.0.4 h1:0XErmfJBiVbl0NvyclGn4jr+1hIylDf5beFi9W0o7Fc= +github.com/decred/dcrd/dcrec/secp256k1 v1.0.4/go.mod h1:00z7mJdugt+GBAzPN1QrDRGCXxyKUiexEHu6ukxEw3k= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 h1:3GIJYXQDAKpLEFriGFN8SbSffak10UXHGdIcFaMPykY= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0/go.mod h1:3s92l0paYkZoIHuj4X93Teg/HB7eGM9x/zokGw+u4mY= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= diff --git a/testutil/keeper/keyshare.go b/testutil/keeper/keyshare.go index 748c1277..7624f2c6 100644 --- a/testutil/keeper/keyshare.go +++ b/testutil/keeper/keyshare.go @@ -1,48 +1,103 @@ package keeper import ( - "testing" - "cosmossdk.io/log" "cosmossdk.io/store" "cosmossdk.io/store/metrics" storetypes "cosmossdk.io/store/types" + pepkeeper "github.com/Fairblock/fairyring/x/pep/keeper" + peptypes "github.com/Fairblock/fairyring/x/pep/types" cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/address" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/runtime" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" portkeeper "github.com/cosmos/ibc-go/v8/modules/core/05-port/keeper" ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + "testing" "github.com/Fairblock/fairyring/x/keyshare/keeper" "github.com/Fairblock/fairyring/x/keyshare/types" ) -func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { +var ( + bondedAcc = authtypes.NewEmptyModuleAccount(stakingtypes.BondedPoolName) + notBondedAcc = authtypes.NewEmptyModuleAccount(stakingtypes.NotBondedPoolName) + PKs = simtestutil.CreateTestPubKeys(500) +) + +func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context, pepkeeper.Keeper, *stakingkeeper.Keeper) { storeKey := storetypes.NewKVStoreKey(types.StoreKey) + pepStoreKey := storetypes.NewKVStoreKey(peptypes.StoreKey) + stakingStoreKey := storetypes.NewKVStoreKey(stakingtypes.StoreKey) memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) + pepMemStoreKey := storetypes.NewMemoryStoreKey(peptypes.MemStoreKey) db := dbm.NewMemDB() stateStore := store.NewCommitMultiStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics()) stateStore.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, db) + stateStore.MountStoreWithDB(pepStoreKey, storetypes.StoreTypeIAVL, db) + stateStore.MountStoreWithDB(stakingStoreKey, storetypes.StoreTypeIAVL, db) stateStore.MountStoreWithDB(memStoreKey, storetypes.StoreTypeMemory, nil) + stateStore.MountStoreWithDB(pepMemStoreKey, storetypes.StoreTypeMemory, nil) require.NoError(t, stateStore.LoadLatestVersion()) registry := codectypes.NewInterfaceRegistry() appCodec := codec.NewProtoCodec(registry) + capabilityKeeper := capabilitykeeper.NewKeeper(appCodec, storeKey, memStoreKey) authority := authtypes.NewModuleAddress(govtypes.ModuleName) - scopedKeeper := capabilityKeeper.ScopeToModule(ibcexported.ModuleName) portKeeper := portkeeper.NewKeeper(scopedKeeper) - // scopeModule := capabilityKeeper.ScopeToModule(types.ModuleName) + + pepCapabilityKeeper := capabilitykeeper.NewKeeper(appCodec, pepStoreKey, pepMemStoreKey) + pepScopedKeeper := pepCapabilityKeeper.ScopeToModule(ibcexported.ModuleName) + pepPortKeeper := portkeeper.NewKeeper(pepScopedKeeper) + + ctrl := gomock.NewController(t) + accountKeeper := stakingtestutil.NewMockAccountKeeper(ctrl) + accountKeeper.EXPECT().GetModuleAddress(stakingtypes.BondedPoolName).Return(bondedAcc.GetAddress()) + accountKeeper.EXPECT().GetModuleAddress(stakingtypes.NotBondedPoolName).Return(notBondedAcc.GetAddress()) + accountKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() + + bankKeeper := stakingtestutil.NewMockBankKeeper(ctrl) + + pepKeeper := pepkeeper.NewKeeper( + appCodec, + runtime.NewKVStoreService(pepStoreKey), + log.NewNopLogger(), + authority.String(), + func() *ibckeeper.Keeper { + return &ibckeeper.Keeper{ + PortKeeper: &pepPortKeeper, + } + }, + pepScopedKeeper, + accountKeeper, + nil, + ) + + stakingKeeper := stakingkeeper.NewKeeper( + appCodec, + runtime.NewKVStoreService(stakingStoreKey), + accountKeeper, + bankKeeper, + authority.String(), + address.NewBech32Codec("cosmosvaloper"), + address.NewBech32Codec("cosmosvalcons"), + ) k := keeper.NewKeeper( appCodec, @@ -58,11 +113,11 @@ func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { //func(string) capabilitykeeper.ScopedKeeper { // return scopeModule //}, + accountKeeper, nil, + pepKeeper, nil, - nil, - nil, - nil, + stakingKeeper, nil, ) @@ -72,6 +127,13 @@ func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { if err := k.SetParams(ctx, types.DefaultParams()); err != nil { panic(err) } + // Initialize params + if err := pepKeeper.SetParams(ctx, peptypes.DefaultParams()); err != nil { + panic(err) + } + if err := stakingKeeper.SetParams(ctx, stakingtypes.DefaultParams()); err != nil { + panic(err) + } - return k, ctx + return k, ctx, pepKeeper, stakingKeeper } diff --git a/testutil/random/pubkey.go b/testutil/random/pubkey.go new file mode 100644 index 00000000..32bc3b15 --- /dev/null +++ b/testutil/random/pubkey.go @@ -0,0 +1,104 @@ +package random + +import ( + "encoding/base64" + "encoding/hex" + distIBE "github.com/FairBlock/DistributedIBE" + "github.com/Fairblock/fairyring/testutil/sample" + "github.com/Fairblock/fairyring/x/keyshare/types" + dcrdSecp256k1 "github.com/decred/dcrd/dcrec/secp256k1" + "github.com/drand/kyber" + bls "github.com/drand/kyber-bls12381" + "math" + "math/big" +) + +type GeneratedShare struct { + Share string + EncShare string + Index kyber.Scalar + PrivateKey *dcrdSecp256k1.PrivateKey + PK *dcrdSecp256k1.PublicKey + ValidatorAddress string +} + +type GenerateResult struct { + GeneratedShare []*GeneratedShare + KeyShareEncryptedKeyShares []*types.EncryptedKeyShare + Commitments []string + MasterPublicKey string +} + +func GeneratePubKeyAndShares(totalNumberOfValidator uint32) (*GenerateResult, error) { + + t := int(math.Ceil(float64(totalNumberOfValidator) * (2.0 / 3.0))) + + shares, mpk, _, err := distIBE.GenerateShares(totalNumberOfValidator, uint32(t)) + if err != nil { + return nil, err + } + + masterPublicKeyByte, err := mpk.MarshalBinary() + if err != nil { + return nil, err + } + + var result GenerateResult + result.MasterPublicKey = hex.EncodeToString(masterPublicKeyByte) + + suite := bls.NewBLS12381Suite() + keyShareCommitments := make([]string, totalNumberOfValidator) + sharesList := make([]*GeneratedShare, totalNumberOfValidator) + + for _, s := range shares { + indexByte, _ := hex.DecodeString(s.Index.String()) + indexInt := big.NewInt(0).SetBytes(indexByte).Uint64() + + commitmentPoints := suite.G1().Point().Mul(s.Value, suite.G1().Point().Base()) + commitmentPointsBinary, _ := commitmentPoints.MarshalBinary() + + keyShareCommitments[indexInt-1] = hex.EncodeToString(commitmentPointsBinary) + + randomAddr := sample.AccAddress() + sb, _ := s.Value.MarshalBinary() + privKey, err := dcrdSecp256k1.GeneratePrivateKey() + if err != nil { + return nil, err + } + + res, err := dcrdSecp256k1.Encrypt(privKey.PubKey(), sb) + if err != nil { + return nil, err + } + + share := GeneratedShare{ + hex.EncodeToString(sb), + base64.StdEncoding.EncodeToString(res), + s.Index, + privKey, + privKey.PubKey(), + randomAddr, + } + + sharesList[indexInt-1] = &share + } + + n := len(sharesList) + + encShares := make([]*types.EncryptedKeyShare, n) + + for _, v := range sharesList { + indexByte, _ := hex.DecodeString(v.Index.String()) + indexInt := big.NewInt(0).SetBytes(indexByte).Uint64() + encShares[indexInt-1] = &types.EncryptedKeyShare{ + Data: v.EncShare, + Validator: v.ValidatorAddress, + } + } + + result.GeneratedShare = sharesList + result.KeyShareEncryptedKeyShares = encShares + result.Commitments = keyShareCommitments + + return &result, nil +} diff --git a/testutil/shares/derive.go b/testutil/shares/derive.go new file mode 100644 index 00000000..3bf395d4 --- /dev/null +++ b/testutil/shares/derive.go @@ -0,0 +1,38 @@ +package shares + +import ( + "encoding/hex" + distIBE "github.com/FairBlock/DistributedIBE" + bls "github.com/drand/kyber-bls12381" +) + +func DeriveShare(hexShare string, shareIndex uint32, id string) (string, error) { + shareByte, err := hex.DecodeString(hexShare) + if err != nil { + return "", err + } + + share := bls.NewKyberScalar() + err = share.UnmarshalBinary(shareByte) + if err != nil { + return "", err + } + + s := bls.NewBLS12381Suite() + extractedKey := distIBE.Extract(s, share, shareIndex, []byte(id)) + + extractedBinary, err := extractedKey.SK.MarshalBinary() + if err != nil { + return "", err + } + extractedKeyHex := hex.EncodeToString(extractedBinary) + + // commitmentPoint := s.G1().Point().Mul(share, s.G1().Point().Base()) + //commitmentBinary, err := commitmentPoint.MarshalBinary() + //if err != nil { + // return "", err + //} + // commitmentHex := hex.EncodeToString(commitmentBinary) + + return extractedKeyHex, nil +} diff --git a/x/keyshare/keeper/aggregated_key_share_request_test.go b/x/keyshare/keeper/aggregated_key_share_request_test.go index 7ecceeb8..418b0581 100644 --- a/x/keyshare/keeper/aggregated_key_share_request_test.go +++ b/x/keyshare/keeper/aggregated_key_share_request_test.go @@ -22,7 +22,7 @@ func createNKeyshareRequest(keeper *keeper.Keeper, ctx sdk.Context, n int) []typ } func TestKeyShareRequestGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNKeyshareRequest(&keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetKeyShareRequest(ctx, @@ -36,7 +36,7 @@ func TestKeyShareRequestGet(t *testing.T) { } } func TestKeyShareRequestRemove(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNKeyshareRequest(&keeper, ctx, 10) for _, item := range items { keeper.RemoveKeyShareRequest(ctx, @@ -50,7 +50,7 @@ func TestKeyShareRequestRemove(t *testing.T) { } func TestKeyShareRequestGetAll(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNKeyshareRequest(&keeper, ctx, 10) require.ElementsMatch(t, nullify.Fill(items), diff --git a/x/keyshare/keeper/aggregated_key_share_test.go b/x/keyshare/keeper/aggregated_key_share_test.go index 6c8110e3..9647e4a6 100644 --- a/x/keyshare/keeper/aggregated_key_share_test.go +++ b/x/keyshare/keeper/aggregated_key_share_test.go @@ -27,7 +27,7 @@ func createNAggregatedKeyShare(keeper *keeper.Keeper, ctx sdk.Context, n int) [] } func TestAggregatedKeyShareGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNAggregatedKeyShare(&keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetAggregatedKeyShare(ctx, @@ -41,7 +41,7 @@ func TestAggregatedKeyShareGet(t *testing.T) { } } func TestAggregatedKeyShareRemove(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNAggregatedKeyShare(&keeper, ctx, 10) for _, item := range items { keeper.RemoveAggregatedKeyShare(ctx, @@ -55,7 +55,7 @@ func TestAggregatedKeyShareRemove(t *testing.T) { } func TestAggregatedKeyShareGetAll(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNAggregatedKeyShare(&keeper, ctx, 10) require.ElementsMatch(t, nullify.Fill(items), diff --git a/x/keyshare/keeper/authorized_address_test.go b/x/keyshare/keeper/authorized_address_test.go index f1a79063..00cb13ec 100644 --- a/x/keyshare/keeper/authorized_address_test.go +++ b/x/keyshare/keeper/authorized_address_test.go @@ -29,7 +29,7 @@ func createNAuthorizedAddress(keeper *keeper.Keeper, ctx sdk.Context, n int) []t } func TestAuthorizedAddressGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNAuthorizedAddress(&keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetAuthorizedAddress(ctx, @@ -43,7 +43,7 @@ func TestAuthorizedAddressGet(t *testing.T) { } } func TestAuthorizedAddressRemove(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNAuthorizedAddress(&keeper, ctx, 10) for _, item := range items { keeper.RemoveAuthorizedAddress(ctx, @@ -57,7 +57,7 @@ func TestAuthorizedAddressRemove(t *testing.T) { } func TestAuthorizedAddressGetAll(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNAuthorizedAddress(&keeper, ctx, 10) require.ElementsMatch(t, nullify.Fill(items), diff --git a/x/keyshare/keeper/commitments_test.go b/x/keyshare/keeper/commitments_test.go index bf618096..70130534 100644 --- a/x/keyshare/keeper/commitments_test.go +++ b/x/keyshare/keeper/commitments_test.go @@ -27,7 +27,7 @@ func createNCommitments(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.C } func TestActiveCommitmentsGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNCommitments(&keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetActiveCommitments(ctx) @@ -40,7 +40,7 @@ func TestActiveCommitmentsGet(t *testing.T) { } func TestQueuedCommitmentsGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNCommitments(&keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetQueuedCommitments(ctx) @@ -53,7 +53,7 @@ func TestQueuedCommitmentsGet(t *testing.T) { } func TestActiveCommitmentsRemove(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) createNCommitments(&keeper, ctx, 10) _, found := keeper.GetActiveCommitments(ctx) require.True(t, found) @@ -64,7 +64,7 @@ func TestActiveCommitmentsRemove(t *testing.T) { } func TestQueuedCommitmentsRemove(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) createNCommitments(&keeper, ctx, 10) _, found := keeper.GetQueuedCommitments(ctx) require.True(t, found) diff --git a/x/keyshare/keeper/general_key_share_test.go b/x/keyshare/keeper/general_key_share_test.go index fe5db5e1..e663814a 100644 --- a/x/keyshare/keeper/general_key_share_test.go +++ b/x/keyshare/keeper/general_key_share_test.go @@ -27,7 +27,7 @@ func createNGeneralKeyShares(keeper *keeper.Keeper, ctx sdk.Context, n int) []ty } func TestGeneralKeyShareGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNGeneralKeyShares(&keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetGeneralKeyShare(ctx, @@ -44,7 +44,7 @@ func TestGeneralKeyShareGet(t *testing.T) { } func TestGeneralKeySharesRemove(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNGeneralKeyShares(&keeper, ctx, 10) keeper.RemoveGeneralKeyShare(ctx, @@ -61,7 +61,7 @@ func TestGeneralKeySharesRemove(t *testing.T) { } func TestGeneralKeySharesGetAll(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNGeneralKeyShares(&keeper, ctx, 10) require.ElementsMatch(t, nullify.Fill(items), diff --git a/x/keyshare/keeper/key_share_test.go b/x/keyshare/keeper/key_share_test.go index 4951b5f1..c8c38aef 100644 --- a/x/keyshare/keeper/key_share_test.go +++ b/x/keyshare/keeper/key_share_test.go @@ -25,7 +25,7 @@ func createNKeyShares(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Key } func TestKeyShareGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNKeyShares(&keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetKeyShare(ctx, @@ -41,7 +41,7 @@ func TestKeyShareGet(t *testing.T) { } func TestKeySharesRemove(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNKeyShares(&keeper, ctx, 10) keeper.RemoveKeyShare(ctx, @@ -56,7 +56,7 @@ func TestKeySharesRemove(t *testing.T) { } func TestKeySharesGetAll(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNKeyShares(&keeper, ctx, 10) require.ElementsMatch(t, nullify.Fill(items), diff --git a/x/keyshare/keeper/last_submitted_height_test.go b/x/keyshare/keeper/last_submitted_height_test.go index bb9661af..c26f41c4 100644 --- a/x/keyshare/keeper/last_submitted_height_test.go +++ b/x/keyshare/keeper/last_submitted_height_test.go @@ -20,7 +20,7 @@ func createLastSubmittedHeight(keeper *keeper.Keeper, ctx sdk.Context) (string, } func TestLastSubmittedHeightGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) val, generatedHeight := createLastSubmittedHeight(&keeper, ctx) height := strconv.FormatUint(keeper.GetLastSubmittedHeight(ctx, val), 10) require.Equal(t, diff --git a/x/keyshare/keeper/msg_authorized_address_test.go b/x/keyshare/keeper/msg_authorized_address_test.go new file mode 100644 index 00000000..e04e73f9 --- /dev/null +++ b/x/keyshare/keeper/msg_authorized_address_test.go @@ -0,0 +1,165 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/sample" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestAuthorizedAddressMsgServerCreate(t *testing.T) { + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + creator := sample.AccAddress() + anotherAddr := sample.AccAddress() + + k.SetValidatorSet(ctx, types.ValidatorSet{ + Index: creator, + Validator: creator, + ConsAddr: "", + IsActive: true, + }) + + expected := &types.MsgCreateAuthorizedAddress{Creator: creator, + Target: anotherAddr, + } + _, err := srv.CreateAuthorizedAddress(wctx, expected) + require.NoError(t, err) + rst, found := k.GetAuthorizedAddress(ctx, + expected.Target, + ) + require.True(t, found) + require.Equal(t, expected.Creator, rst.AuthorizedBy) +} + +func TestAuthorizedAddressMsgServerUpdate(t *testing.T) { + creator := sample.AccAddress() + target := sample.AccAddress() + + for _, tc := range []struct { + desc string + request *types.MsgUpdateAuthorizedAddress + err error + }{ + { + desc: "Completed", + request: &types.MsgUpdateAuthorizedAddress{Creator: creator, + Target: target, + }, + }, + { + desc: "Unauthorized", + request: &types.MsgUpdateAuthorizedAddress{Creator: "B", + Target: target, + }, + err: types.ErrNotAuthorizedAddrCreator, + }, + { + desc: "KeyNotFound", + request: &types.MsgUpdateAuthorizedAddress{Creator: creator, + Target: strconv.Itoa(100000), + }, + err: types.ErrAuthorizedAddrNotFound, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + k.SetValidatorSet(ctx, types.ValidatorSet{ + Index: creator, + Validator: creator, + ConsAddr: "", + IsActive: true, + }) + + expected := &types.MsgCreateAuthorizedAddress{Creator: creator, + Target: target, + } + _, err := srv.CreateAuthorizedAddress(wctx, expected) + require.NoError(t, err) + + _, err = srv.UpdateAuthorizedAddress(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + rst, found := k.GetAuthorizedAddress(ctx, + expected.Target, + ) + require.True(t, found) + require.Equal(t, expected.Creator, rst.AuthorizedBy) + } + }) + } +} + +func TestAuthorizedAddressMsgServerDelete(t *testing.T) { + creator := sample.AccAddress() + target := sample.AccAddress() + + for _, tc := range []struct { + desc string + request *types.MsgDeleteAuthorizedAddress + err error + }{ + { + desc: "Completed", + request: &types.MsgDeleteAuthorizedAddress{Creator: creator, + Target: target, + }, + }, + { + desc: "RemovedByTarget", + request: &types.MsgDeleteAuthorizedAddress{Creator: target, + Target: target, + }, + }, + { + desc: "KeyNotFound", + request: &types.MsgDeleteAuthorizedAddress{Creator: creator, + Target: strconv.Itoa(100000), + }, + err: types.ErrAuthorizedAddrNotFound, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + k.SetValidatorSet(ctx, types.ValidatorSet{ + Index: creator, + Validator: creator, + ConsAddr: "", + IsActive: true, + }) + + _, err := srv.CreateAuthorizedAddress(wctx, &types.MsgCreateAuthorizedAddress{Creator: creator, + Target: target, + }) + require.NoError(t, err) + _, err = srv.DeleteAuthorizedAddress(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + _, found := k.GetAuthorizedAddress(ctx, + tc.request.Target, + ) + require.False(t, found) + } + }) + } +} diff --git a/x/keyshare/keeper/msg_create_general_key_share_test.go b/x/keyshare/keeper/msg_create_general_key_share_test.go new file mode 100644 index 00000000..310ff328 --- /dev/null +++ b/x/keyshare/keeper/msg_create_general_key_share_test.go @@ -0,0 +1,240 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/shares" + types2 "github.com/Fairblock/fairyring/x/pep/types" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func SetupTestGeneralKeyShare(t *testing.T, ctx sdk.Context, k keeper.Keeper, numberOfValidator uint32, pubkeyNumberOfValidator uint64) (*random.GenerateResult, string) { + out, err := random.GeneratePubKeyAndShares(numberOfValidator) + require.NoError(t, err) + + creator := out.GeneratedShare[0].ValidatorAddress + + k.SetValidatorSet(ctx, types.ValidatorSet{ + Index: creator, + Validator: creator, + ConsAddr: "", + IsActive: true, + }) + + k.SetActivePubKey(ctx, types.ActivePubKey{ + PublicKey: out.MasterPublicKey, + Creator: creator, + Expiry: 123456, + NumberOfValidators: pubkeyNumberOfValidator, + EncryptedKeyShares: out.KeyShareEncryptedKeyShares, + }) + + k.SetActiveCommitments(ctx, types.Commitments{ + Commitments: out.Commitments, + }) + + return out, creator +} + +func TestGeneralKeyShareMsgServerCreateAggregated(t *testing.T) { + + k, ctx, pk, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + out, creator := SetupTestGeneralKeyShare(t, wctx, k, 1, 1) + + for i := 0; i < 5; i++ { + + idVal := random.RandHex(32) + + k.SetKeyShareRequest(wctx, types.KeyShareRequest{ + Identity: idVal, + Pubkey: out.MasterPublicKey, + IbcInfo: nil, + Counterparty: nil, + AggrKeyshare: "", + ProposalId: "", + RequestId: idVal, + Sent: false, + }) + pk.SetEntry(wctx, types2.GenEncTxExecutionQueue{ + Creator: creator, + RequestId: idVal, + Identity: idVal, + Pubkey: out.MasterPublicKey, + TxList: nil, + AggrKeyshare: "", + }) + + derived, err := shares.DeriveShare(out.GeneratedShare[0].Share, 1, idVal) + require.NoError(t, err) + + expected := &types.MsgCreateGeneralKeyShare{Creator: creator, + IdType: keeper.PrivateGovIdentity, + IdValue: idVal, + KeyShareIndex: 1, + KeyShare: derived, + } + + _, err = srv.CreateGeneralKeyShare(wctx, expected) + require.NoError(t, err) + + rst, found := k.GetGeneralKeyShare(wctx, + expected.Creator, + expected.IdType, + expected.IdValue, + ) + require.True(t, found) + require.Equal(t, expected.Creator, rst.Validator) + + entry, found := k.GetKeyShareRequest(ctx, idVal) + require.True(t, found) + require.NotEmpty(t, entry.AggrKeyshare) + } +} + +func TestGeneralKeyShareMsgServerCreateNotAggregated(t *testing.T) { + + k, ctx, pk, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + out, creator := SetupTestGeneralKeyShare(t, wctx, k, 10, 10) + + for i := 0; i < 5; i++ { + + idVal := random.RandHex(32) + + k.SetKeyShareRequest(wctx, types.KeyShareRequest{ + Identity: idVal, + Pubkey: out.MasterPublicKey, + IbcInfo: nil, + Counterparty: nil, + AggrKeyshare: "", + ProposalId: "", + RequestId: idVal, + Sent: false, + }) + pk.SetEntry(wctx, types2.GenEncTxExecutionQueue{ + Creator: creator, + RequestId: idVal, + Identity: idVal, + Pubkey: out.MasterPublicKey, + TxList: nil, + AggrKeyshare: "", + }) + + derived, err := shares.DeriveShare(out.GeneratedShare[0].Share, 1, idVal) + require.NoError(t, err) + + expected := &types.MsgCreateGeneralKeyShare{Creator: creator, + IdType: keeper.PrivateGovIdentity, + IdValue: idVal, + KeyShareIndex: 1, + KeyShare: derived, + } + + _, err = srv.CreateGeneralKeyShare(wctx, expected) + require.NoError(t, err) + + rst, found := k.GetGeneralKeyShare(wctx, + expected.Creator, + expected.IdType, + expected.IdValue, + ) + require.True(t, found) + require.Equal(t, expected.Creator, rst.Validator) + + entry, found := k.GetKeyShareRequest(ctx, idVal) + require.True(t, found) + require.Empty(t, entry.AggrKeyshare) + } +} + +func TestGeneralKeyShareMsgServerFailCases(t *testing.T) { + k, ctx, pk, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + out, creator := SetupTestGeneralKeyShare(t, wctx, k, 1, 1) + onlyIdVal := random.RandHex(32) + + pk.SetEntry(wctx, types2.GenEncTxExecutionQueue{ + Creator: creator, + RequestId: onlyIdVal, + Identity: onlyIdVal, + Pubkey: out.MasterPublicKey, + TxList: nil, + AggrKeyshare: "", + }) + + for _, tc := range []struct { + desc string + request *types.MsgCreateGeneralKeyShare + err error + }{ + { + desc: "Unauthorized", + request: &types.MsgCreateGeneralKeyShare{Creator: "B"}, + err: types.ErrAddrIsNotValidatorOrAuthorized, + }, + { + desc: "NotSupportedIDType", + request: &types.MsgCreateGeneralKeyShare{ + Creator: creator, + IdType: "not_exists", + }, + err: types.ErrUnsupportedIDType, + }, + { + desc: "KeyShareRequestNotFound", + request: &types.MsgCreateGeneralKeyShare{ + Creator: creator, + IdType: keeper.PrivateGovIdentity, + IdValue: random.RandHex(32), + }, + err: types.ErrKeyShareRequestNotFound, + }, + { + desc: "InvalidKeyShareIndex", + request: &types.MsgCreateGeneralKeyShare{ + Creator: creator, + IdType: keeper.PrivateGovIdentity, + IdValue: onlyIdVal, + KeyShareIndex: 10, + }, + err: types.ErrInvalidKeyShareIndex, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + + _, err := srv.CreateGeneralKeyShare(wctx, tc.request) + + require.ErrorIs(t, err, tc.err) + + if tc.desc == "KeyShareRequestNotFound" { + k.SetKeyShareRequest(wctx, types.KeyShareRequest{ + Identity: onlyIdVal, + Pubkey: out.MasterPublicKey, + IbcInfo: nil, + Counterparty: nil, + AggrKeyshare: "", + ProposalId: "", + RequestId: onlyIdVal, + Sent: false, + }) + } + }) + } +} diff --git a/x/keyshare/keeper/msg_create_pub_key_test.go b/x/keyshare/keeper/msg_create_pub_key_test.go new file mode 100644 index 00000000..a5770365 --- /dev/null +++ b/x/keyshare/keeper/msg_create_pub_key_test.go @@ -0,0 +1,84 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestLatestPubKeyMsgServerCreate(t *testing.T) { + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + out, err := random.GeneratePubKeyAndShares(1) + require.NoError(t, err) + + creator := out.GeneratedShare[0].ValidatorAddress + + params := types.DefaultParams() + params.TrustedAddresses = append(params.TrustedAddresses, creator) + err = k.SetParams(wctx, params) + require.NoError(t, err) + + k.SetQueuedPubKey(wctx, types.QueuedPubKey{ + PublicKey: out.MasterPublicKey, + Creator: creator, + Expiry: 123456, + NumberOfValidators: 1, + EncryptedKeyShares: out.KeyShareEncryptedKeyShares, + }) + + for _, tc := range []struct { + desc string + request *types.MsgCreateLatestPubKey + err error + }{ + { + desc: "Unauthorized", + request: &types.MsgCreateLatestPubKey{Creator: "B"}, + err: types.ErrAddressNotTrusted, + }, + { + desc: "QueuedKeyAlreadyExists", + request: &types.MsgCreateLatestPubKey{ + Creator: creator, + }, + err: types.ErrQueuedKeyAlreadyExists, + }, + { + desc: "SuccessCreatePubKey", + request: &types.MsgCreateLatestPubKey{ + PublicKey: out.MasterPublicKey, + Creator: creator, + NumberOfValidators: 1, + EncryptedKeyShares: out.KeyShareEncryptedKeyShares, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + + _, err := srv.CreateLatestPubKey(wctx, tc.request) + + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + } + + if tc.desc == "QueuedKeyAlreadyExists" { + k.DeleteQueuedPubKey(wctx) + } + }) + } +} diff --git a/x/keyshare/keeper/msg_deregister_validator_test.go b/x/keyshare/keeper/msg_deregister_validator_test.go new file mode 100644 index 00000000..f9e73940 --- /dev/null +++ b/x/keyshare/keeper/msg_deregister_validator_test.go @@ -0,0 +1,56 @@ +package keeper_test + +import ( + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/sample" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "testing" +) + +func TestDeRegisterValidatorMsgServer(t *testing.T) { + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + creator := sample.AccAddress() + + k.SetValidatorSet(wctx, types.ValidatorSet{ + Index: creator, + Validator: creator, + ConsAddr: "", + IsActive: true, + }) + + for _, tc := range []struct { + desc string + request *types.MsgDeRegisterValidator + err error + }{ + { + desc: "ValidatorNotRegistered", + request: &types.MsgDeRegisterValidator{ + Creator: sample.AccAddress(), + }, + err: types.ErrValidatorNotRegistered, + }, + { + desc: "SuccessfullyDeRegisterValidator", + request: &types.MsgDeRegisterValidator{ + Creator: creator, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + + _, err := srv.DeRegisterValidator(wctx, tc.request) + + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/keyshare/keeper/msg_override_pub_key_test.go b/x/keyshare/keeper/msg_override_pub_key_test.go new file mode 100644 index 00000000..2784a248 --- /dev/null +++ b/x/keyshare/keeper/msg_override_pub_key_test.go @@ -0,0 +1,70 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestOverrideLatestPubKeyMsgServer(t *testing.T) { + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + out, err := random.GeneratePubKeyAndShares(1) + require.NoError(t, err) + + creator := out.GeneratedShare[0].ValidatorAddress + + params := types.DefaultParams() + params.TrustedAddresses = append(params.TrustedAddresses, creator) + err = k.SetParams(wctx, params) + require.NoError(t, err) + + for _, tc := range []struct { + desc string + request *types.MsgOverrideLatestPubKey + err error + }{ + { + desc: "Unauthorized", + request: &types.MsgOverrideLatestPubKey{Creator: "B"}, + err: types.ErrAddressNotTrusted, + }, + { + desc: "SuccessOverridePubKey", + request: &types.MsgOverrideLatestPubKey{ + PublicKey: out.MasterPublicKey, + Creator: creator, + Commitments: out.Commitments, + NumberOfValidators: 1, + EncryptedKeyShares: out.KeyShareEncryptedKeyShares, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + + _, err := srv.OverrideLatestPubKey(wctx, tc.request) + + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + } + + if tc.desc == "QueuedKeyAlreadyExists" { + k.DeleteQueuedPubKey(wctx) + } + }) + } +} diff --git a/x/keyshare/keeper/msg_register_validator_test.go b/x/keyshare/keeper/msg_register_validator_test.go new file mode 100644 index 00000000..fd292e33 --- /dev/null +++ b/x/keyshare/keeper/msg_register_validator_test.go @@ -0,0 +1,77 @@ +package keeper_test + +import ( + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/sample" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "testing" +) + +func TestRegisterValidatorMsgServer(t *testing.T) { + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + creator := sample.AccAddress() + //newValAddr := keeper2.RandomAccountAddress(t) + + k.SetValidatorSet(wctx, types.ValidatorSet{ + Index: creator, + Validator: creator, + ConsAddr: "", + IsActive: true, + }) + + for _, tc := range []struct { + desc string + request *types.MsgRegisterValidator + err error + }{ + { + desc: "ValidatorAlreadyRegistered", + request: &types.MsgRegisterValidator{ + Creator: creator, + }, + err: types.ErrValidatorAlreadyRegistered, + }, + { + desc: "ValidatorNotStaking", + request: &types.MsgRegisterValidator{ + Creator: sample.AccAddress(), + }, + err: types.ErrAccountNotStaking, + }, + //{ + // desc: "SuccessfullyRegisteredAsValidator", + // request: &types.MsgRegisterValidator{ + // Creator: newValAddr.String(), + // }, + //}, + } { + t.Run(tc.desc, func(t *testing.T) { + + _, err := srv.RegisterValidator(wctx, tc.request) + + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + } + + //if tc.desc == "ValidatorNotStaking" { + // valAddr := sdk.ValAddress(keepertest.PKs[0].Address().Bytes()) + // val := stakingtestutil.NewValidator(t, valAddr, keepertest.PKs[0]) + // val.AddTokensFromDel(math.NewIntFromUint64(k.MinimumBonded(wctx) * 2)) + // val.Status = stakingtypes.Bonded + // + // err = stakingKeeper.SetValidator(wctx, val) + // require.NoError(t, err) + // out, err := stakingKeeper.GetValidator(wctx, valAddr) + // require.NoError(t, err) + // require.Equal(t, out.OperatorAddress, valAddr) + //} + }) + } +} diff --git a/x/keyshare/keeper/msg_send_key_share_test.go b/x/keyshare/keeper/msg_send_key_share_test.go new file mode 100644 index 00000000..cf783323 --- /dev/null +++ b/x/keyshare/keeper/msg_send_key_share_test.go @@ -0,0 +1,128 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/shares" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestSendKeyShareMsgServerCreateAggregated(t *testing.T) { + + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + out, creator := SetupTestGeneralKeyShare(t, wctx, k, 1, 1) + + var idUint uint64 = 1 + + derived, err := shares.DeriveShare(out.GeneratedShare[0].Share, 1, "1") + require.NoError(t, err) + + expected := &types.MsgSendKeyshare{Creator: creator, + Message: derived, + KeyShareIndex: idUint, + BlockHeight: idUint, + } + + _, err = srv.SendKeyshare(wctx, expected) + require.NoError(t, err) + + rst, found := k.GetKeyShare(wctx, + expected.Creator, + idUint, + ) + require.True(t, found) + require.Equal(t, expected.Creator, rst.Validator) + + _, found = k.GetAggregatedKeyShare(wctx, idUint) + require.True(t, found) + +} + +func TestSendKeyShareMsgServerCreateNotAggregated(t *testing.T) { + + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + out, creator := SetupTestGeneralKeyShare(t, wctx, k, 10, 10) + + var idUint uint64 = 1 + + derived, err := shares.DeriveShare(out.GeneratedShare[0].Share, 1, "1") + require.NoError(t, err) + + expected := &types.MsgSendKeyshare{Creator: creator, + Message: derived, + KeyShareIndex: idUint, + BlockHeight: idUint, + } + + _, err = srv.SendKeyshare(wctx, expected) + require.NoError(t, err) + + rst, found := k.GetKeyShare(wctx, + expected.Creator, + idUint, + ) + require.True(t, found) + require.Equal(t, expected.Creator, rst.Validator) + + _, found = k.GetAggregatedKeyShare(wctx, idUint) + require.False(t, found) +} + +func TestSendKeyShareMsgServerFailCases(t *testing.T) { + k, ctx, _, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + _, creator := SetupTestGeneralKeyShare(t, wctx, k, 1, 1) + + for _, tc := range []struct { + desc string + request *types.MsgSendKeyshare + err error + }{ + { + desc: "Unauthorized", + request: &types.MsgSendKeyshare{Creator: "B"}, + err: types.ErrAddrIsNotValidatorOrAuthorized, + }, + { + desc: "InvalidBlockHeight", + request: &types.MsgSendKeyshare{ + Creator: creator, + BlockHeight: 999, + }, + err: types.ErrInvalidBlockHeight, + }, + { + desc: "InvalidKeyShareIndex", + request: &types.MsgSendKeyshare{ + Creator: creator, + KeyShareIndex: 999, + }, + err: types.ErrInvalidKeyShareIndex, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + + _, err := srv.SendKeyshare(wctx, tc.request) + + require.ErrorIs(t, err, tc.err) + + }) + } +} diff --git a/x/keyshare/keeper/msg_server_test.go b/x/keyshare/keeper/msg_server_test.go index eba2436a..22df5e9a 100644 --- a/x/keyshare/keeper/msg_server_test.go +++ b/x/keyshare/keeper/msg_server_test.go @@ -12,7 +12,7 @@ import ( ) func setupMsgServer(t testing.TB) (keeper.Keeper, types.MsgServer, context.Context) { - k, ctx := keepertest.KeyshareKeeper(t) + k, ctx, _, _ := keepertest.KeyshareKeeper(t) return k, keeper.NewMsgServerImpl(k), ctx } diff --git a/x/keyshare/keeper/params_test.go b/x/keyshare/keeper/params_test.go index a14b4c19..9e178272 100644 --- a/x/keyshare/keeper/params_test.go +++ b/x/keyshare/keeper/params_test.go @@ -10,7 +10,7 @@ import ( ) func TestGetParams(t *testing.T) { - k, ctx := keepertest.KeyshareKeeper(t) + k, ctx, _, _ := keepertest.KeyshareKeeper(t) params := types.DefaultParams() require.NoError(t, k.SetParams(ctx, params)) diff --git a/x/keyshare/keeper/pub_key_test.go b/x/keyshare/keeper/pub_key_test.go index 02024f7a..6de56c81 100644 --- a/x/keyshare/keeper/pub_key_test.go +++ b/x/keyshare/keeper/pub_key_test.go @@ -32,7 +32,7 @@ func createQueuedPubKeys(keeper *keeper.Keeper, ctx sdk.Context) types.QueuedPub } func TestActivePubKeyGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) item := createActivePubKeys(&keeper, ctx) rst, found := keeper.GetActivePubKey(ctx) require.True(t, found) @@ -43,7 +43,7 @@ func TestActivePubKeyGet(t *testing.T) { } func TestQueuedPubKeyGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) item := createQueuedPubKeys(&keeper, ctx) rst, found := keeper.GetQueuedPubKey(ctx) require.True(t, found) @@ -54,7 +54,7 @@ func TestQueuedPubKeyGet(t *testing.T) { } func TestActivePubKeyRemoved(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) createActivePubKeys(&keeper, ctx) keeper.DeleteActivePubKey(ctx) _, found := keeper.GetActivePubKey(ctx) @@ -62,7 +62,7 @@ func TestActivePubKeyRemoved(t *testing.T) { } func TestQueuedPubKeyRemoved(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) createQueuedPubKeys(&keeper, ctx) keeper.DeleteQueuedPubKey(ctx) _, found := keeper.GetQueuedPubKey(ctx) diff --git a/x/keyshare/keeper/query_aggregated_key_share_test.go b/x/keyshare/keeper/query_aggregated_key_share_test.go index bce00426..b0631b15 100644 --- a/x/keyshare/keeper/query_aggregated_key_share_test.go +++ b/x/keyshare/keeper/query_aggregated_key_share_test.go @@ -19,7 +19,7 @@ import ( var _ = strconv.IntSize func TestAggregatedKeyShareQuerySingle(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNAggregatedKeyShare(&keeper, ctx, 2) for _, tc := range []struct { @@ -70,7 +70,7 @@ func TestAggregatedKeyShareQuerySingle(t *testing.T) { } func TestAggregatedKeyShareQueryAllNoPagination(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNAggregatedKeyShare(&keeper, ctx, 10) for _, tc := range []struct { @@ -115,7 +115,7 @@ func TestAggregatedKeyShareQueryAllNoPagination(t *testing.T) { } func TestAggregatedKeyShareQueryPaginated(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNAggregatedKeyShare(&keeper, ctx, 5) diff --git a/x/keyshare/keeper/query_authorized_address_test.go b/x/keyshare/keeper/query_authorized_address_test.go index 07582f00..88ed99d0 100644 --- a/x/keyshare/keeper/query_authorized_address_test.go +++ b/x/keyshare/keeper/query_authorized_address_test.go @@ -19,7 +19,7 @@ import ( var _ = strconv.IntSize func TestAuthorizedAddressQuerySingle(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNAuthorizedAddress(&keeper, ctx, 2) for _, tc := range []struct { @@ -70,7 +70,7 @@ func TestAuthorizedAddressQuerySingle(t *testing.T) { } func TestAuthorizedAddressQueryAllNoPagination(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNAuthorizedAddress(&keeper, ctx, 12) for _, tc := range []struct { @@ -115,7 +115,7 @@ func TestAuthorizedAddressQueryAllNoPagination(t *testing.T) { } func TestAuthorizedAddressQueryPaginated(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNAuthorizedAddress(&keeper, ctx, 5) diff --git a/x/keyshare/keeper/query_commitments_test.go b/x/keyshare/keeper/query_commitments_test.go index 3ad76fc6..ae3e3ddd 100644 --- a/x/keyshare/keeper/query_commitments_test.go +++ b/x/keyshare/keeper/query_commitments_test.go @@ -15,7 +15,7 @@ import ( var _ = strconv.IntSize func TestCommitmentsQuery(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNCommitments(&keeper, ctx, 1) for _, tc := range []struct { diff --git a/x/keyshare/keeper/query_general_key_share_test.go b/x/keyshare/keeper/query_general_key_share_test.go index 11d29e91..9e24d1e9 100644 --- a/x/keyshare/keeper/query_general_key_share_test.go +++ b/x/keyshare/keeper/query_general_key_share_test.go @@ -19,7 +19,7 @@ import ( var _ = strconv.IntSize func TestGeneralKeyShareQuerySingle(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNGeneralKeyShares(&keeper, ctx, 2) for _, tc := range []struct { @@ -76,7 +76,7 @@ func TestGeneralKeyShareQuerySingle(t *testing.T) { } func TestGeneralKeyShareQueryAllNoPagination(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNGeneralKeyShares(&keeper, ctx, 10) for _, tc := range []struct { @@ -121,7 +121,7 @@ func TestGeneralKeyShareQueryAllNoPagination(t *testing.T) { } func TestGeneralKeyShareQueryPaginated(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNGeneralKeyShares(&keeper, ctx, 5) diff --git a/x/keyshare/keeper/query_key_share_test.go b/x/keyshare/keeper/query_key_share_test.go index 9262a2bc..e0ccd433 100644 --- a/x/keyshare/keeper/query_key_share_test.go +++ b/x/keyshare/keeper/query_key_share_test.go @@ -21,7 +21,7 @@ import ( var _ = strconv.IntSize func TestKeyShareQuerySingle(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNKeyShares(&keeper, ctx, 2) for _, tc := range []struct { @@ -75,7 +75,7 @@ func TestKeyShareQuerySingle(t *testing.T) { } func TestKeyShareQueryAllNoPagination(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNKeyShares(&keeper, ctx, 10) for _, tc := range []struct { @@ -120,7 +120,7 @@ func TestKeyShareQueryAllNoPagination(t *testing.T) { } func TestKeyShareQueryPaginated(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) wctx := sdk.UnwrapSDKContext(ctx) msgs := createNKeyShares(&keeper, ctx, 5) diff --git a/x/keyshare/keeper/query_params_test.go b/x/keyshare/keeper/query_params_test.go index ca409af6..acf4b284 100644 --- a/x/keyshare/keeper/query_params_test.go +++ b/x/keyshare/keeper/query_params_test.go @@ -1,20 +1,50 @@ package keeper_test import ( - "testing" - - "github.com/stretchr/testify/require" - keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "testing" ) func TestParamsQuery(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) params := types.DefaultParams() - require.NoError(t, keeper.SetParams(ctx, params)) - - response, err := keeper.Params(ctx, &types.QueryParamsRequest{}) - require.NoError(t, err) - require.Equal(t, &types.QueryParamsResponse{Params: params}, response) + keeper.SetParams(ctx, params) + for _, tc := range []struct { + desc string + request *types.QueryParamsRequest + response *types.QueryParamsResponse + err error + }{ + { + desc: "QueryParams", + request: &types.QueryParamsRequest{}, + response: &types.QueryParamsResponse{ + Params: params, + }, + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.Params(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } } diff --git a/x/keyshare/keeper/query_pub_key_test.go b/x/keyshare/keeper/query_pub_key_test.go new file mode 100644 index 00000000..6cac3ee5 --- /dev/null +++ b/x/keyshare/keeper/query_pub_key_test.go @@ -0,0 +1,51 @@ +package keeper_test + +import ( + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "testing" +) + +func TestPubKeyQuery(t *testing.T) { + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + activePubKey := createActivePubKeys(&keeper, wctx) + queuedPubKey := createQueuedPubKeys(&keeper, wctx) + for _, tc := range []struct { + desc string + request *types.QueryPubKeyRequest + response *types.QueryPubKeyResponse + err error + }{ + { + desc: "QueryPubKey", + request: &types.QueryPubKeyRequest{}, + response: &types.QueryPubKeyResponse{ + ActivePubKey: activePubKey, + QueuedPubKey: queuedPubKey, + }, + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.PubKey(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} diff --git a/x/keyshare/keeper/query_validator_set_test.go b/x/keyshare/keeper/query_validator_set_test.go new file mode 100644 index 00000000..59b99358 --- /dev/null +++ b/x/keyshare/keeper/query_validator_set_test.go @@ -0,0 +1,172 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/sample" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestValidatorSetQuerySingle(t *testing.T) { + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNValidatorSet(&keeper, ctx, 2) + for _, tc := range []struct { + desc string + request *types.QueryGetValidatorSetRequest + response *types.QueryGetValidatorSetResponse + err error + }{ + { + desc: "First", + request: &types.QueryGetValidatorSetRequest{ + Index: msgs[0].Index, + }, + response: &types.QueryGetValidatorSetResponse{ValidatorSet: msgs[0]}, + }, + { + desc: "Second", + request: &types.QueryGetValidatorSetRequest{ + Index: msgs[1].Index, + }, + response: &types.QueryGetValidatorSetResponse{ValidatorSet: msgs[1]}, + }, + { + desc: "KeyNotFound", + request: &types.QueryGetValidatorSetRequest{ + Index: sample.AccAddress(), + }, + err: status.Error(codes.NotFound, "not found"), + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.ValidatorSet(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestValidatorSetQueryAllNoPagination(t *testing.T) { + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNValidatorSet(&keeper, ctx, 10) + for _, tc := range []struct { + desc string + request *types.QueryAllValidatorSetRequest + response *types.QueryAllValidatorSetResponse + err error + }{ + { + desc: "QueryAllValidatorSet", + request: &types.QueryAllValidatorSetRequest{ + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 0, + CountTotal: false, + Reverse: false, + }, + }, + response: &types.QueryAllValidatorSetResponse{ + ValidatorSet: msgs, + Pagination: &query.PageResponse{ + NextKey: nil, + Total: 10, + }, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.ValidatorSetAll(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestValidatorSetQueryPaginated(t *testing.T) { + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNValidatorSet(&keeper, ctx, 5) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllValidatorSetRequest { + return &types.QueryAllValidatorSetRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.ValidatorSetAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.ValidatorSet), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.ValidatorSet), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.ValidatorSetAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.ValidatorSet), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.ValidatorSet), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.ValidatorSetAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.ValidatorSet), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.ValidatorSetAll(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) + }) +} diff --git a/x/keyshare/keeper/query_verifiable_randomness_test.go b/x/keyshare/keeper/query_verifiable_randomness_test.go new file mode 100644 index 00000000..f443cd2d --- /dev/null +++ b/x/keyshare/keeper/query_verifiable_randomness_test.go @@ -0,0 +1,103 @@ +package keeper_test + +import ( + "crypto/sha256" + "encoding/hex" + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/x/keyshare/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "math/rand" + "testing" +) + +func TestVerifiableRandomnessQuery(t *testing.T) { + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + + for _, tc := range []struct { + desc string + request *types.QueryVerifiableRandomnessQuery + response *types.QueryVerifiableRandomnessResponse + err error + }{ + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + { + desc: "AggregatedKeyNotFound", + request: &types.QueryVerifiableRandomnessQuery{}, + err: status.Error(codes.Internal, "aggregated key not found"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.VerifiableRandomness(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } + + randomHeight := rand.Uint64() + + keeper.SetAggregatedKeyShare(ctx, types.AggregatedKeyShare{ + Height: randomHeight, + Data: "NotHexString", + }) + + randomData := random.RandHex(64) + randomBytes, _ := hex.DecodeString(randomData) + + hash := sha256.New() + hash.Write(randomBytes) + hashedAggrKey := hash.Sum(nil) + + for _, tc := range []struct { + desc string + request *types.QueryVerifiableRandomnessQuery + response *types.QueryVerifiableRandomnessResponse + err error + }{ + { + desc: "UnableDecodeAggregatedKey", + request: &types.QueryVerifiableRandomnessQuery{}, + err: status.Error(codes.Internal, "unable to decode aggregated key"), + }, + { + desc: "QueryVerifiableRandomness", + request: &types.QueryVerifiableRandomnessQuery{}, + response: &types.QueryVerifiableRandomnessResponse{ + Randomness: hex.EncodeToString(hashedAggrKey), + Round: randomHeight + 1, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.VerifiableRandomness(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + keeper.SetAggregatedKeyShare(ctx, types.AggregatedKeyShare{ + Height: randomHeight + 1, + Data: randomData, + }) + } +} diff --git a/x/keyshare/keeper/validator_set_test.go b/x/keyshare/keeper/validator_set_test.go index d5854188..16c8d44a 100644 --- a/x/keyshare/keeper/validator_set_test.go +++ b/x/keyshare/keeper/validator_set_test.go @@ -26,7 +26,7 @@ func createNValidatorSet(keeper *keeper.Keeper, ctx sdk.Context, n int) []types. } func TestValidatorSetGet(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNValidatorSet(&keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetValidatorSet(ctx, @@ -41,7 +41,7 @@ func TestValidatorSetGet(t *testing.T) { } func TestValidatorSetRemove(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNValidatorSet(&keeper, ctx, 10) keeper.RemoveValidatorSet(ctx, @@ -54,7 +54,7 @@ func TestValidatorSetRemove(t *testing.T) { } func TestValidatorSetGetAll(t *testing.T) { - keeper, ctx := keepertest.KeyshareKeeper(t) + keeper, ctx, _, _ := keepertest.KeyshareKeeper(t) items := createNValidatorSet(&keeper, ctx, 10) require.ElementsMatch(t, nullify.Fill(items), From a0e4d515a0a10fd9af9c4cf5e98609d80a12e811 Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Mon, 30 Sep 2024 21:48:55 -0400 Subject: [PATCH 17/41] Override init cmd --- cmd/fairyringd/cmd/commands.go | 6 +- cmd/fairyringd/cmd/init.go | 188 +++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 cmd/fairyringd/cmd/init.go diff --git a/cmd/fairyringd/cmd/commands.go b/cmd/fairyringd/cmd/commands.go index e1946f17..2b6b5b0c 100644 --- a/cmd/fairyringd/cmd/commands.go +++ b/cmd/fairyringd/cmd/commands.go @@ -2,9 +2,10 @@ package cmd import ( "errors" - "github.com/Fairblock/fairyring/cmd/fairyringd/cmd/secp_encrypter" "io" + "github.com/Fairblock/fairyring/cmd/fairyringd/cmd/secp_encrypter" + "cosmossdk.io/log" confixcmd "cosmossdk.io/tools/confix/cmd" "github.com/CosmWasm/wasmd/x/wasm" @@ -39,7 +40,8 @@ func initRootCmd( basicManager module.BasicManager, ) { rootCmd.AddCommand( - genutilcli.InitCmd(basicManager, app.DefaultNodeHome), + InitCmd(basicManager, app.DefaultNodeHome), + // genutilcli.InitCmd(basicManager, app.DefaultNodeHome), debug.Cmd(), confixcmd.ConfigCommand(), pruning.Cmd(newApp, app.DefaultNodeHome), diff --git a/cmd/fairyringd/cmd/init.go b/cmd/fairyringd/cmd/init.go new file mode 100644 index 00000000..8e4bbcaa --- /dev/null +++ b/cmd/fairyringd/cmd/init.go @@ -0,0 +1,188 @@ +package cmd + +import ( + "bufio" + "encoding/json" + "errors" + "fmt" + "os" + "path/filepath" + "time" + + cfg "github.com/cometbft/cometbft/config" + "github.com/cosmos/go-bip39" + "github.com/spf13/cobra" + + errorsmod "cosmossdk.io/errors" + "cosmossdk.io/math/unsafe" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/input" + "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/cosmos/cosmos-sdk/x/genutil/types" +) + +const ( + // FlagOverwrite defines a flag to overwrite an existing genesis JSON file. + FlagOverwrite = "overwrite" + + // FlagSeed defines a flag to initialize the private validator key from a specific seed. + FlagRecover = "recover" + + // FlagDefaultBondDenom defines the default denom to use in the genesis file. + FlagDefaultBondDenom = "default-denom" +) + +type printInfo struct { + Moniker string `json:"moniker" yaml:"moniker"` + ChainID string `json:"chain_id" yaml:"chain_id"` + NodeID string `json:"node_id" yaml:"node_id"` + GenTxsDir string `json:"gentxs_dir" yaml:"gentxs_dir"` + AppMessage json.RawMessage `json:"app_message" yaml:"app_message"` +} + +func newPrintInfo(moniker, chainID, nodeID, genTxsDir string, appMessage json.RawMessage) printInfo { + return printInfo{ + Moniker: moniker, + ChainID: chainID, + NodeID: nodeID, + GenTxsDir: genTxsDir, + AppMessage: appMessage, + } +} + +func displayInfo(info printInfo) error { + out, err := json.MarshalIndent(info, "", " ") + if err != nil { + return err + } + + _, err = fmt.Fprintf(os.Stderr, "%s\n", out) + + return err +} + +// InitCmd returns a command that initializes all files needed for Tendermint +// and the respective application. +func InitCmd(mbm module.BasicManager, defaultNodeHome string) *cobra.Command { + cmd := &cobra.Command{ + Use: "init [moniker]", + Short: "Initialize private validator, p2p, genesis, and application configuration files", + Long: `Initialize validators's and node's configuration files.`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + cdc := clientCtx.Codec + + serverCtx := server.GetServerContextFromCmd(cmd) + config := serverCtx.Config + config.SetRoot(clientCtx.HomeDir) + + // Update to a 1 second block time + config.Consensus.TimeoutCommit = time.Second + + chainID, _ := cmd.Flags().GetString(flags.FlagChainID) + switch { + case chainID != "": + case clientCtx.ChainID != "": + chainID = clientCtx.ChainID + default: + chainID = fmt.Sprintf("test-chain-%v", unsafe.Str(6)) + } + + // Get bip39 mnemonic + var mnemonic string + recover, _ := cmd.Flags().GetBool(FlagRecover) + if recover { + inBuf := bufio.NewReader(cmd.InOrStdin()) + value, err := input.GetString("Enter your bip39 mnemonic", inBuf) + if err != nil { + return err + } + + mnemonic = value + if !bip39.IsMnemonicValid(mnemonic) { + return errors.New("invalid mnemonic") + } + } + + // Get initial height + initHeight, _ := cmd.Flags().GetInt64(flags.FlagInitHeight) + if initHeight < 1 { + initHeight = 1 + } + + nodeID, _, err := genutil.InitializeNodeValidatorFilesFromMnemonic(config, mnemonic) + if err != nil { + return err + } + + config.Moniker = args[0] + + genFile := config.GenesisFile() + overwrite, _ := cmd.Flags().GetBool(FlagOverwrite) + defaultDenom, _ := cmd.Flags().GetString(FlagDefaultBondDenom) + + // use os.Stat to check if the file exists + _, err = os.Stat(genFile) + if !overwrite && !os.IsNotExist(err) { + return fmt.Errorf("genesis.json file already exists: %v", genFile) + } + + // Overwrites the SDK default denom for side-effects + if defaultDenom != "" { + sdk.DefaultBondDenom = defaultDenom + } + appGenState := mbm.DefaultGenesis(cdc) + + appState, err := json.MarshalIndent(appGenState, "", " ") + if err != nil { + return errorsmod.Wrap(err, "Failed to marshal default genesis state") + } + + appGenesis := &types.AppGenesis{} + if _, err := os.Stat(genFile); err != nil { + if !os.IsNotExist(err) { + return err + } + } else { + appGenesis, err = types.AppGenesisFromFile(genFile) + if err != nil { + return errorsmod.Wrap(err, "Failed to read genesis doc from file") + } + } + + appGenesis.AppName = version.AppName + appGenesis.AppVersion = version.Version + appGenesis.ChainID = chainID + appGenesis.AppState = appState + appGenesis.InitialHeight = initHeight + appGenesis.Consensus = &types.ConsensusGenesis{ + Validators: nil, + } + + if err = genutil.ExportGenesisFile(appGenesis, genFile); err != nil { + return errorsmod.Wrap(err, "Failed to export genesis file") + } + + toPrint := newPrintInfo(config.Moniker, chainID, nodeID, "", appState) + + cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) + return displayInfo(toPrint) + }, + } + + cmd.Flags().String(flags.FlagHome, defaultNodeHome, "node's home directory") + cmd.Flags().BoolP(FlagOverwrite, "o", false, "overwrite the genesis.json file") + cmd.Flags().Bool(FlagRecover, false, "provide seed phrase to recover existing key instead of creating") + cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") + cmd.Flags().String(FlagDefaultBondDenom, "", "genesis file default denomination, if left blank default value is 'stake'") + cmd.Flags().Int64(flags.FlagInitHeight, 1, "specify the initial block height at genesis") + + return cmd +} From e16dda711c716da87773cce2519625eb949cf65d Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Mon, 30 Sep 2024 22:49:33 -0400 Subject: [PATCH 18/41] Add encrypted keyshare tests --- testutil/shares/encrypt.go | 30 ++++ ...re.go => msg_submit_encrypted_keyshare.go} | 11 ++ .../msg_submit_encrypted_keyshare_test.go | 151 ++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 testutil/shares/encrypt.go rename x/keyshare/keeper/{msg_server_submit_encrypted_keyshare.go => msg_submit_encrypted_keyshare.go} (93%) create mode 100644 x/keyshare/keeper/msg_submit_encrypted_keyshare_test.go diff --git a/testutil/shares/encrypt.go b/testutil/shares/encrypt.go new file mode 100644 index 00000000..4c01434b --- /dev/null +++ b/testutil/shares/encrypt.go @@ -0,0 +1,30 @@ +package shares + +import ( + "encoding/base64" + "encoding/hex" + "github.com/btcsuite/btcd/btcec" +) + +// EncryptWithPublicKey encrypts data using an RSA public key. +func EncryptWithPublicKey(data string, pubKeyBase64 string) (string, error) { + // Decode the base64 public key + pubKeyBytes, err := base64.StdEncoding.DecodeString(pubKeyBase64) + if err != nil { + return "", err + } + + // Load the secp256k1 public key + pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256()) + if err != nil { + return "", err + } + + ciphertext, err := btcec.Encrypt(pubKey, []byte(data)) + if err != nil { + return "", err + } + + // Encode ciphertext as hex for easy handling + return hex.EncodeToString(ciphertext), nil +} diff --git a/x/keyshare/keeper/msg_server_submit_encrypted_keyshare.go b/x/keyshare/keeper/msg_submit_encrypted_keyshare.go similarity index 93% rename from x/keyshare/keeper/msg_server_submit_encrypted_keyshare.go rename to x/keyshare/keeper/msg_submit_encrypted_keyshare.go index 434ab567..26aee3e5 100644 --- a/x/keyshare/keeper/msg_server_submit_encrypted_keyshare.go +++ b/x/keyshare/keeper/msg_submit_encrypted_keyshare.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "fmt" "strconv" "time" @@ -39,6 +40,16 @@ func (k msgServer) SubmitEncryptedKeyshare(goCtx context.Context, msg *types.Msg return nil, types.ErrKeyShareRequestNotFound.Wrapf(", got id value: %s", msg.Identity) } + commitments, found := k.GetActiveCommitments(ctx) + if !found { + return nil, types.ErrCommitmentsNotFound + } + + commitmentsLen := uint64(len(commitments.Commitments)) + if msg.KeyShareIndex > commitmentsLen { + return nil, types.ErrInvalidKeyShareIndex.Wrap(fmt.Sprintf("Expect Index within: %d, got: %d", commitmentsLen, msg.KeyShareIndex)) + } + valEncKeyshare := types.ValidatorEncryptedKeyShare{ Validator: msg.Creator, Requester: msg.Requester, diff --git a/x/keyshare/keeper/msg_submit_encrypted_keyshare_test.go b/x/keyshare/keeper/msg_submit_encrypted_keyshare_test.go new file mode 100644 index 00000000..1e03d45c --- /dev/null +++ b/x/keyshare/keeper/msg_submit_encrypted_keyshare_test.go @@ -0,0 +1,151 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/shares" + commontypes "github.com/Fairblock/fairyring/x/common/types" + types2 "github.com/Fairblock/fairyring/x/pep/types" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/keyshare/keeper" + "github.com/Fairblock/fairyring/x/keyshare/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +const SECP_PUBKEY_1 = "A/MdHVpitzHNSdD1Zw3kY+L5PEIPyd9l6sD5i4aIfXp9" + +func TestEncryptedlKeyShareMsgServerCreate(t *testing.T) { + + k, ctx, pk, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + out, creator := SetupTestGeneralKeyShare(t, wctx, k, 1, 1) + + for i := 0; i < 5; i++ { + + idVal := random.RandHex(32) + + k.SetPrivateKeyShareRequest(wctx, types.PrivateKeyshareRequest{ + Identity: idVal, + Pubkey: out.MasterPublicKey, + IbcInfo: nil, + Counterparty: nil, + RequestId: idVal, + Sent: false, + EncryptedKeyshares: make([]*commontypes.EncryptedKeyshare, 0), + }) + pk.SetPrivateRequest(wctx, types2.PrivateRequest{ + Creator: creator, + ReqId: idVal, + Pubkey: out.MasterPublicKey, + EncryptedKeyshares: make([]*commontypes.EncryptedKeyshare, 0), + }) + pk.SetPrivateReqQueueEntry(wctx, commontypes.RequestPrivateKeyshare{ + Creator: creator, + RequestId: idVal, + }) + + derived, err := shares.DeriveShare(out.GeneratedShare[0].Share, 1, idVal) + require.NoError(t, err) + + encryptedShare, err := shares.EncryptWithPublicKey(derived, SECP_PUBKEY_1) + require.NoError(t, err) + + expected := &types.MsgSubmitEncryptedKeyshare{Creator: creator, + KeyShareIndex: 1, + Identity: idVal, + EncryptedKeyshare: encryptedShare, + Requester: creator, + } + + _, err = srv.SubmitEncryptedKeyshare(wctx, expected) + require.NoError(t, err) + + _, found := k.GetPrivateKeyShareRequest(ctx, idVal) + require.True(t, found) + + rst, found := k.GetPrivateKeyShare(wctx, + expected.Creator, + expected.Identity, + expected.Creator, + ) + require.True(t, found) + require.Equal(t, expected.Creator, rst.Validator) + } +} + +func TestEncryptedKeyShareMsgServerFailCases(t *testing.T) { + k, ctx, pk, _ := keepertest.KeyshareKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + out, creator := SetupTestGeneralKeyShare(t, wctx, k, 1, 1) + onlyIdVal := random.RandHex(32) + + pk.SetPrivateReqQueueEntry(wctx, commontypes.RequestPrivateKeyshare{ + Creator: creator, + RequestId: onlyIdVal, + }) + + for _, tc := range []struct { + desc string + request *types.MsgSubmitEncryptedKeyshare + err error + }{ + { + desc: "Unauthorized", + request: &types.MsgSubmitEncryptedKeyshare{Creator: "B"}, + err: types.ErrAddrIsNotValidatorOrAuthorized, + }, + { + desc: "KeyShareRequestNotFound", + request: &types.MsgSubmitEncryptedKeyshare{ + Creator: creator, + Identity: random.RandHex(32), + }, + err: types.ErrKeyShareRequestNotFound, + }, + { + desc: "InvalidKeyShareIndex", + request: &types.MsgSubmitEncryptedKeyshare{ + Creator: creator, + Identity: onlyIdVal, + KeyShareIndex: 10, + }, + err: types.ErrInvalidKeyShareIndex, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + + _, err := srv.SubmitEncryptedKeyshare(wctx, tc.request) + + require.ErrorIs(t, err, tc.err) + + if tc.desc == "KeyShareRequestNotFound" { + k.SetPrivateKeyShareRequest(wctx, types.PrivateKeyshareRequest{ + Identity: onlyIdVal, + Pubkey: out.MasterPublicKey, + IbcInfo: nil, + Counterparty: nil, + RequestId: onlyIdVal, + Sent: false, + EncryptedKeyshares: make([]*commontypes.EncryptedKeyshare, 0), + }) + pk.SetPrivateRequest(wctx, types2.PrivateRequest{ + Creator: creator, + ReqId: onlyIdVal, + Pubkey: out.MasterPublicKey, + EncryptedKeyshares: make([]*commontypes.EncryptedKeyshare, 0), + }) + } + }) + } +} From d0f954d56b5668358ffcb17f89e318540e88089a Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Tue, 1 Oct 2024 09:35:19 +0530 Subject: [PATCH 19/41] Revert "removing misnomer error" This reverts commit dcc90df163c0346d5044880a47467656601ac019. --- x/keyshare/keeper/msg_create_general_key_share.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/keyshare/keeper/msg_create_general_key_share.go b/x/keyshare/keeper/msg_create_general_key_share.go index 238622fd..a720b4a9 100644 --- a/x/keyshare/keeper/msg_create_general_key_share.go +++ b/x/keyshare/keeper/msg_create_general_key_share.go @@ -67,7 +67,7 @@ func (k msgServer) CreateGeneralKeyShare(goCtx context.Context, msg *types.MsgCr return nil, types.ErrKeyShareRequestNotFound.Wrapf(", got id value: %s", msg.IdValue) } if keyShareReq.AggrKeyshare != "" { - return &types.MsgCreateGeneralKeyShareResponse{}, nil + return nil, types.ErrAggKeyAlreadyExists.Wrapf(", identity: %s, Aggregated key: %s", msg.IdValue, keyShareReq.AggrKeyshare) } } From 6a792ff221533e8f49a2bd5a2213c8faf16d55db Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Tue, 1 Oct 2024 20:38:30 +0530 Subject: [PATCH 20/41] minor fix --- api/fairyring/pep/query.pulsar.go | 35 ++-- app/ibc.go | 1 + fairyring_contract/Cargo.lock | 186 +----------------- fairyring_contract/Cargo.toml | 12 +- fairyring_contract/artifacts/checksums.txt | 1 + .../artifacts/fairyring_contract.wasm | Bin 0 -> 195179 bytes fairyring_contract/src/contract.rs | 36 ++-- fairyring_contract/src/msg.rs | 12 ++ go.mod | 4 +- go.sum | 4 +- proto/fairyring/pep/query.proto | 2 +- scripts/tests/pep.sh | 14 +- x/pep/types/query.pb.go | 168 ++++++++-------- x/pep/types/query.pb.gw.go | 42 ++-- 14 files changed, 176 insertions(+), 341 deletions(-) create mode 100644 fairyring_contract/artifacts/checksums.txt create mode 100644 fairyring_contract/artifacts/fairyring_contract.wasm diff --git a/api/fairyring/pep/query.pulsar.go b/api/fairyring/pep/query.pulsar.go index a15813bd..87742372 100644 --- a/api/fairyring/pep/query.pulsar.go +++ b/api/fairyring/pep/query.pulsar.go @@ -12052,7 +12052,7 @@ var file_fairyring_pep_query_proto_rawDesc = []byte{ 0x72, 0x79, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, - 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x32, 0xee, 0x0d, 0x0a, + 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x32, 0xf7, 0x0d, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x6e, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x21, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, @@ -12152,28 +12152,29 @@ var file_fairyring_pep_query_proto_rawDesc = []byte{ 0x12, 0x3a, 0x2f, 0x46, 0x61, 0x69, 0x72, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, - 0x5f, 0x72, 0x65, 0x71, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x49, 0x64, 0x7d, 0x12, 0xae, 0x01, 0x0a, + 0x5f, 0x72, 0x65, 0x71, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x49, 0x64, 0x7d, 0x12, 0xb7, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4e, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x12, 0x46, 0x2f, 0x46, 0x61, 0x69, 0x72, 0x62, 0x6c, 0x6f, 0x63, + 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x57, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x51, 0x12, 0x4f, 0x2f, 0x46, 0x61, 0x69, 0x72, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0x2f, - 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x7b, 0x61, 0x67, - 0x67, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x7d, 0x2f, 0x7b, 0x65, 0x6e, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x7d, 0x42, 0x94, 0x01, - 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x65, 0x70, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, - 0x70, 0xa2, 0x02, 0x03, 0x46, 0x50, 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, - 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, - 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, - 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, - 0x3a, 0x50, 0x65, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x7b, 0x70, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x7d, 0x2f, 0x7b, 0x61, 0x67, 0x67, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, + 0x68, 0x61, 0x72, 0x65, 0x7d, 0x2f, 0x7b, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, + 0x5f, 0x64, 0x61, 0x74, 0x61, 0x7d, 0x42, 0x94, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, + 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x42, 0x0a, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x61, 0x69, + 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0xa2, 0x02, 0x03, 0x46, 0x50, 0x58, + 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x70, + 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, + 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x46, + 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x50, 0x65, 0x70, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/app/ibc.go b/app/ibc.go index b1276e8b..028c1014 100644 --- a/app/ibc.go +++ b/app/ibc.go @@ -172,6 +172,7 @@ func (app *App) registerIBCModules(appOpts servertypes.AppOptions) error { acceptList := map[string]proto.Message{ "/fairyring.keyshare.Query/VerifiableRandomness": &keysharemoduletypes.QueryVerifiableRandomnessResponse{}, + "/fairyring.pep.Query/DecryptData": &pepmoduletypes.QueryDecryptDataResponse{}, } // Add wasmd to IBC Router diff --git a/fairyring_contract/Cargo.lock b/fairyring_contract/Cargo.lock index 0b0e163e..9a66d06d 100644 --- a/fairyring_contract/Cargo.lock +++ b/fairyring_contract/Cargo.lock @@ -302,12 +302,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e31ea183f6ee62ac8b8a8cf7feddd766317adfb13ff469de57ce033efd6a790" -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - [[package]] name = "byteorder" version = "1.5.0" @@ -323,15 +317,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cc" -version = "1.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17" -dependencies = [ - "shlex", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -726,15 +711,9 @@ dependencies = [ "cw-multi-test", "cw-storage-plus", "fairblock-proto", - "getrandom", - "mio", - "prost", - "prost-types", "schemars", "serde", "thiserror", - "tokio", - "tonic", ] [[package]] @@ -825,10 +804,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] @@ -949,9 +926,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1056,15 +1033,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "js-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" -dependencies = [ - "wasm-bindgen", -] - [[package]] name = "k256" version = "0.13.4" @@ -1083,12 +1051,6 @@ version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - [[package]] name = "matchit" version = "0.7.3" @@ -1124,7 +1086,6 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", - "log", "wasi", "windows-sys", ] @@ -1377,21 +1338,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys", -] - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1407,48 +1353,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustls" -version = "0.23.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" -dependencies = [ - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" -dependencies = [ - "base64", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - [[package]] name = "rustversion" version = "1.0.17" @@ -1576,12 +1480,6 @@ dependencies = [ "digest", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "signature" version = "2.2.0" @@ -1617,12 +1515,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "static_assertions" version = "1.1.0" @@ -1770,17 +1662,6 @@ dependencies = [ "syn 2.0.79", ] -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.16" @@ -1826,10 +1707,8 @@ dependencies = [ "percent-encoding", "pin-project", "prost", - "rustls-pemfile", "socket2", "tokio", - "tokio-rustls", "tokio-stream", "tower 0.4.13", "tower-layer", @@ -1938,12 +1817,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "version_check" version = "0.9.5" @@ -1965,61 +1838,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.79", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" - [[package]] name = "windows-sys" version = "0.52.0" diff --git a/fairyring_contract/Cargo.toml b/fairyring_contract/Cargo.toml index 64b63052..a250198a 100644 --- a/fairyring_contract/Cargo.toml +++ b/fairyring_contract/Cargo.toml @@ -39,13 +39,13 @@ cw-storage-plus = "2.0.0" serde = { version = "1.0", features = ["derive"] } schemars = "0.8" thiserror = "1.0" -prost = "0.13.3" # Protobuf support -prost-types = "0.13" -tonic = { version = "0.12.3", features = ["prost", "tls"] } +# prost = "0.13.3" # Protobuf support +# prost-types = "0.13" +# tonic = { version = "0.12.3", features = ["prost", "tls"] } fairblock-proto = { git = "https://github.com/Fairblock/fairblock-rust/", branch = "contract-callback" } -getrandom = { version = "0.2", features = ["js"] } -mio = "1.0.2" -tokio = "1.40.0" +# getrandom = { version = "0.2", features = ["js"] } +# mio = "1.0.2" +# tokio = "1.40.0" [dev-dependencies] cw-multi-test = "2.0.0" \ No newline at end of file diff --git a/fairyring_contract/artifacts/checksums.txt b/fairyring_contract/artifacts/checksums.txt new file mode 100644 index 00000000..8591b19e --- /dev/null +++ b/fairyring_contract/artifacts/checksums.txt @@ -0,0 +1 @@ +3c3274ea81c813cd396a2536e81ca8b899eaabba8e0529cf31a5b127190ab68b fairyring_contract.wasm diff --git a/fairyring_contract/artifacts/fairyring_contract.wasm b/fairyring_contract/artifacts/fairyring_contract.wasm new file mode 100644 index 0000000000000000000000000000000000000000..d759437af2ace0aa1599f58c21162caed91c397c GIT binary patch literal 195179 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 Q{Q(SDF#xWgGRhqP1~qY{E&u=k literal 0 HcmV?d00001 diff --git a/fairyring_contract/src/contract.rs b/fairyring_contract/src/contract.rs index 76cd416e..0328aac5 100644 --- a/fairyring_contract/src/contract.rs +++ b/fairyring_contract/src/contract.rs @@ -1,9 +1,8 @@ // contract.rs -use cosmwasm_std::{attr, entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; -use fairblock_proto::fairyring::pep::query_client::QueryClient; -use fairblock_proto::fairyring::pep::QueryDecryptDataRequest; +use cosmwasm_std::{attr, entry_point, to_json_binary, to_json_string, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; use crate::msg::{ExecuteContractMsg, QueryMsg, QueryResponse, InstantiateMsg}; use crate::state::STORED_DATA; +use fairblock_proto::fairyring::pep::QueryDecryptDataRequest; #[entry_point] pub fn execute( @@ -41,8 +40,8 @@ pub fn execute( #[entry_point] -pub async fn query<'a>( - deps: Deps<'a, QueryMsg>, +pub fn query( + deps: Deps, _env: Env, msg: QueryMsg, ) -> StdResult { @@ -69,7 +68,7 @@ pub async fn query<'a>( } // Call the function to query the `pep` module - let response = query_pep_decrypt(deps, pubkey, aggr_keyshare, encrypted_data).await?; + let response = query_pep_decrypt(deps, pubkey, aggr_keyshare, encrypted_data)?; // Return the decrypted data in binary format to_json_binary(&response) @@ -102,17 +101,12 @@ pub fn instantiate( // Function to query the `DecryptData` RPC from your `pep` module -pub async fn query_pep_decrypt<'a>( - _deps: Deps<'a, QueryMsg>, // Explicitly add lifetime `'a` +pub fn query_pep_decrypt( + deps: Deps, pubkey: String, aggr_keyshare: String, encrypted_data: String, -) -> StdResult { - // Create a gRPC connection to the `pep` module - let mut client = QueryClient::connect("http://localhost:9090") - .await - .map_err(|err| StdError::generic_err(format!("Failed to connect to gRPC server: {}", err)))?; - +) -> StdResult { // Create the request message let request = QueryDecryptDataRequest { pubkey, @@ -120,14 +114,8 @@ pub async fn query_pep_decrypt<'a>( encrypted_data, }; - // Call the decrypt_data method - let response = client - .decrypt_data(request) - .await - .map_err(|err| StdError::generic_err(format!("gRPC query failed: {}", err)))?; - - // Extract the decrypted data from the response - let decrypted_data = response.into_inner().decrypted_data; - - Ok(decrypted_data) + // Send the query + let raw_response: Binary = deps.querier.query_grpc("/fairyring.pep.Query/DecryptData".to_string(), to_json_binary(&request)?)?; + + Ok(raw_response) } \ No newline at end of file diff --git a/fairyring_contract/src/msg.rs b/fairyring_contract/src/msg.rs index 7e8d3e6a..82605af1 100644 --- a/fairyring_contract/src/msg.rs +++ b/fairyring_contract/src/msg.rs @@ -32,6 +32,18 @@ pub struct QueryResponse { pub aggr_keyshare: String, } +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct QueryDecryptDataRequest { + pub pubkey: String, + pub aggr_keyshare: String, + pub encrypted_data: String, +} + +// #[derive(Clone, PartialEq, prost::Message)] +// pub struct QueryDecryptDataResponse { +// #[prost(string, tag = "1")] +// pub decrypted_data: String, +// } // Instantiate message #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/go.mod b/go.mod index 2b22821f..67819d40 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22.4 replace ( cosmossdk.io/api => github.com/Fairblock/cosmossdk-api v0.7.5 - github.com/CosmWasm/wasmd => ../wasmd + github.com/CosmWasm/wasmd => github.com/Fairblock/wasmd v0.50.6-fairyring github.com/cosmos/cosmos-sdk => github.com/Fairblock/cosmos-sdk v0.50.8-fairyring // fix upstream GHSA-h395-qcrw-5vmq vulnerability. github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 @@ -61,8 +61,6 @@ require ( google.golang.org/protobuf v1.34.1 ) -require github.com/regen-network/cosmos-proto v0.3.1 // indirect - require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 // indirect cloud.google.com/go v0.112.0 // indirect diff --git a/go.sum b/go.sum index 9f40c5de..94de3d02 100644 --- a/go.sum +++ b/go.sum @@ -243,6 +243,8 @@ github.com/Fairblock/cosmos-sdk v0.50.8-fairyring h1:b/nFqDT2lHXtam2KdN0s9RLVsYH github.com/Fairblock/cosmos-sdk v0.50.8-fairyring/go.mod h1:ep1ZTLXL8h62Xi6l6lJdto/Xt8CYlP+GW9MudPCT05w= github.com/Fairblock/cosmossdk-api v0.7.5 h1:2NON/rKYquaTpISPn5sOZTP80a2moKg7YN+HI7wi5Wk= github.com/Fairblock/cosmossdk-api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +github.com/Fairblock/wasmd v0.50.6-fairyring h1:P5bEeEQbyLew8dD/kXP1JSjBB6ersyhORcnuYQp3+nI= +github.com/Fairblock/wasmd v0.50.6-fairyring/go.mod h1:f0oj8Oy6bzleydH5ytWMqQD7DCp23b2VKkdsTVmiLrE= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= @@ -1009,8 +1011,6 @@ github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43Z github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= -github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= diff --git a/proto/fairyring/pep/query.proto b/proto/fairyring/pep/query.proto index d60c1c49..db71194a 100644 --- a/proto/fairyring/pep/query.proto +++ b/proto/fairyring/pep/query.proto @@ -82,7 +82,7 @@ service Query { // Queries a list of DecryptData items. rpc DecryptData (QueryDecryptDataRequest) returns (QueryDecryptDataResponse) { - option (google.api.http).get = "/Fairblock/fairyring/pep/decrypt_data/{aggr_keyshare}/{encrypted_data}"; + option (google.api.http).get = "/Fairblock/fairyring/pep/decrypt_data/{pubkey}/{aggr_keyshare}/{encrypted_data}"; } } diff --git a/scripts/tests/pep.sh b/scripts/tests/pep.sh index 580a3fa6..63090280 100755 --- a/scripts/tests/pep.sh +++ b/scripts/tests/pep.sh @@ -810,8 +810,20 @@ echo "#############################################" echo "# Testing contract callback on source chain #" echo "#############################################" +cd $CONTRACT_DIR + +echo "Compiling contract" +cargo build --release --target wasm32-unknown-unknown + +echo "Optimizing Contract" +docker run --rm -v "$(pwd)":/code \ + --mount type=volume,source="$(basename "$(pwd)")_cache",target=/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + cosmwasm/optimizer:0.16.0 +cd - + echo "Deploying smart contract on source chain" -RESULT=$($BINARY tx wasm store $CONTRACT_DIR/optimized_contract.wasm --from $WALLET_1 --gas 9000000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test --fees 9000000ufairy -o json -y) +RESULT=$($BINARY tx wasm store $CONTRACT_DIR/artifacts/fairyring_contract.wasm --from $WALLET_1 --gas 9000000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test --fees 9000000ufairy -o json -y) check_tx_code $RESULT sleep 10 diff --git a/x/pep/types/query.pb.go b/x/pep/types/query.pb.go index bb0491f5..7044ff6c 100644 --- a/x/pep/types/query.pb.go +++ b/x/pep/types/query.pb.go @@ -1178,92 +1178,92 @@ func init() { func init() { proto.RegisterFile("fairyring/pep/query.proto", fileDescriptor_dd36cf23112e8be0) } var fileDescriptor_dd36cf23112e8be0 = []byte{ - // 1352 bytes of a gzipped FileDescriptorProto + // 1357 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x98, 0xcf, 0x6f, 0xe3, 0x44, 0x14, 0xc7, 0xeb, 0x6e, 0x9b, 0x6d, 0x27, 0x6d, 0x05, 0xb3, 0xfd, 0x91, 0x7a, 0xb7, 0x69, 0x77, - 0xd2, 0x5f, 0x44, 0x10, 0xab, 0xed, 0x1e, 0xa0, 0xe2, 0x92, 0xd2, 0x1f, 0xbb, 0x14, 0x2d, 0x6d, - 0x28, 0x1c, 0xf6, 0x12, 0x4d, 0xec, 0xc1, 0xb1, 0x9a, 0xd8, 0x8e, 0xed, 0x74, 0x13, 0xa2, 0x48, - 0x68, 0x2f, 0x5c, 0x38, 0x20, 0x71, 0x47, 0x1c, 0xf7, 0x04, 0x5c, 0xf7, 0x0c, 0x87, 0x3d, 0xae, - 0xc4, 0x85, 0x13, 0x42, 0x2d, 0x12, 0x37, 0xfe, 0x06, 0xe4, 0xf1, 0x73, 0x62, 0x3b, 0x4e, 0xd2, - 0x8a, 0x5e, 0xaa, 0x7a, 0xe6, 0xfd, 0xf8, 0xbc, 0x37, 0xe3, 0xf7, 0x75, 0x8b, 0x16, 0xbf, 0xa4, - 0x9a, 0xd5, 0xb4, 0x34, 0x5d, 0x95, 0x4c, 0x66, 0x4a, 0xb5, 0x3a, 0xb3, 0x9a, 0x39, 0xd3, 0x32, - 0x1c, 0x03, 0x4f, 0x77, 0xb6, 0x72, 0x26, 0x33, 0xc5, 0xb7, 0x69, 0x55, 0xd3, 0x0d, 0x89, 0xff, - 0xf4, 0x2c, 0xc4, 0x59, 0xd5, 0x50, 0x0d, 0xfe, 0xab, 0xe4, 0xfe, 0x06, 0xab, 0x0f, 0x54, 0xc3, - 0x50, 0x2b, 0x4c, 0xa2, 0xa6, 0x26, 0x51, 0x5d, 0x37, 0x1c, 0xea, 0x68, 0x86, 0x6e, 0xc3, 0x6e, - 0x56, 0x36, 0xec, 0xaa, 0x61, 0x4b, 0x25, 0x6a, 0x33, 0x2f, 0x9d, 0x74, 0xb1, 0x55, 0x62, 0x0e, - 0xdd, 0x92, 0x4c, 0xaa, 0x6a, 0x3a, 0x37, 0x06, 0x5b, 0x31, 0x0c, 0x67, 0x52, 0x8b, 0x56, 0xfd, - 0x38, 0x2b, 0xe1, 0x3d, 0xa6, 0xcb, 0x56, 0xd3, 0x74, 0x98, 0x52, 0x74, 0x1a, 0x60, 0xb1, 0x14, - 0xf1, 0x66, 0x66, 0x51, 0x37, 0x74, 0x99, 0xc1, 0xf6, 0x66, 0x78, 0x9b, 0xaa, 0xaa, 0xc5, 0x54, - 0xea, 0x46, 0x38, 0x67, 0xcd, 0xa2, 0x5d, 0xa6, 0x96, 0x6f, 0x99, 0xe9, 0x5a, 0xca, 0x46, 0xb5, - 0x6a, 0xe8, 0x12, 0xdf, 0x55, 0x8a, 0x4e, 0xd3, 0x64, 0x3e, 0x4f, 0x3a, 0x58, 0x97, 0x5f, 0x91, - 0x6c, 0x68, 0x50, 0x0b, 0x99, 0x45, 0xf8, 0xd4, 0xad, 0xf6, 0x84, 0x17, 0x51, 0x60, 0xb5, 0x3a, - 0xb3, 0x1d, 0xf2, 0x29, 0xba, 0x17, 0x5a, 0xb5, 0x4d, 0x43, 0xb7, 0x19, 0x7e, 0x1f, 0x25, 0xbc, - 0x62, 0x53, 0xc2, 0x8a, 0xb0, 0x99, 0xdc, 0x9e, 0xcb, 0x85, 0xce, 0x22, 0xe7, 0x99, 0xef, 0x4d, - 0xbe, 0xfe, 0x73, 0x79, 0xe4, 0xe5, 0x3f, 0xbf, 0x64, 0x85, 0x02, 0xd8, 0x93, 0xf7, 0xd0, 0x2c, - 0x0f, 0x78, 0xcc, 0x9a, 0x1c, 0x12, 0x12, 0xe1, 0x39, 0x94, 0xb0, 0x58, 0xad, 0xa8, 0x29, 0x3c, - 0xe2, 0x64, 0x61, 0xdc, 0x62, 0xb5, 0x27, 0x0a, 0x79, 0x86, 0xe6, 0x22, 0xe6, 0x40, 0x90, 0x47, - 0x13, 0xe7, 0xb0, 0x06, 0x0c, 0x6b, 0x11, 0x86, 0x23, 0xa6, 0x1f, 0xe8, 0xf2, 0x59, 0xe3, 0xa0, - 0xc1, 0xe4, 0xba, 0x7b, 0x68, 0xa7, 0x75, 0x56, 0x67, 0x85, 0x8e, 0x1b, 0xa1, 0x68, 0x81, 0xc7, - 0xce, 0x57, 0x2a, 0x51, 0x9a, 0x43, 0x84, 0xba, 0x87, 0x0d, 0xf1, 0xd7, 0x73, 0x5e, 0x07, 0x73, - 0x6e, 0x07, 0x73, 0xde, 0x45, 0x84, 0x3e, 0xe6, 0x4e, 0xa8, 0xea, 0xfb, 0x16, 0x02, 0x9e, 0xe4, - 0xa5, 0x80, 0x52, 0xbd, 0x39, 0xa0, 0x84, 0x8f, 0xd0, 0xa4, 0xcf, 0xe2, 0xf6, 0xf1, 0xce, 0xf5, - 0x6b, 0xe8, 0xfa, 0xe1, 0xa3, 0x10, 0xe9, 0x28, 0x27, 0xdd, 0x18, 0x4a, 0xea, 0x11, 0x84, 0x50, - 0xbf, 0x40, 0x22, 0x27, 0x3d, 0x62, 0xce, 0x81, 0x7f, 0x57, 0xcf, 0x1a, 0x7e, 0x43, 0x08, 0x9a, - 0x72, 0xa8, 0xa5, 0x32, 0xe7, 0x31, 0xd3, 0xd4, 0xb2, 0xc3, 0x5b, 0x32, 0x56, 0x08, 0xad, 0xe1, - 0x59, 0x34, 0xae, 0xe9, 0x0a, 0x6b, 0x70, 0x8a, 0xb1, 0x82, 0xf7, 0x40, 0x28, 0xba, 0x1f, 0x1b, - 0x17, 0x9a, 0xb0, 0x87, 0x92, 0xac, 0xbb, 0x0c, 0xad, 0x16, 0x23, 0x6d, 0x08, 0x38, 0xee, 0x8d, - 0xb9, 0x77, 0xaa, 0x10, 0x74, 0x22, 0x0a, 0xa0, 0xe7, 0x2b, 0x95, 0x18, 0xf4, 0xdb, 0x3a, 0xcb, - 0x57, 0x02, 0x54, 0x12, 0x4d, 0x03, 0x95, 0x9c, 0xa2, 0xb7, 0x02, 0x50, 0x79, 0xcb, 0xa2, 0x4d, - 0x38, 0xd5, 0xe5, 0xfe, 0xe5, 0x70, 0x33, 0xa8, 0xa9, 0xc7, 0xfd, 0xf6, 0x0e, 0xf7, 0x63, 0xb4, - 0x1a, 0x83, 0x7e, 0x68, 0x19, 0x55, 0xef, 0xec, 0x6e, 0x70, 0xcc, 0xe4, 0x2b, 0xb4, 0x36, 0x24, - 0xd6, 0xc0, 0x86, 0x08, 0xff, 0xa3, 0x21, 0x44, 0x84, 0xd7, 0xe9, 0x13, 0xea, 0x30, 0xdb, 0x09, - 0xb1, 0x93, 0x1d, 0xb4, 0x18, 0xb3, 0x07, 0x2c, 0xf3, 0x28, 0x51, 0x0e, 0x96, 0x04, 0x4f, 0x64, - 0x07, 0x66, 0xc0, 0x11, 0x73, 0x4e, 0x98, 0xf9, 0xd4, 0x1d, 0xbf, 0x7e, 0x2f, 0x52, 0xe8, 0x2e, - 0x55, 0x14, 0x8b, 0xd9, 0x36, 0x8c, 0x24, 0xff, 0x91, 0x7c, 0x0e, 0x14, 0x21, 0x27, 0x48, 0xf4, - 0x01, 0x9a, 0x30, 0x61, 0x0d, 0x8a, 0x5d, 0x88, 0xce, 0x46, 0xd8, 0x86, 0x22, 0x3b, 0xe6, 0xc1, - 0x79, 0x14, 0x65, 0xb9, 0xad, 0x3b, 0xfc, 0x43, 0x60, 0x1e, 0x0d, 0x41, 0xbf, 0x73, 0x03, 0xf4, - 0xdb, 0xbb, 0xa8, 0x1d, 0x15, 0xaa, 0x97, 0x8e, 0x59, 0xd3, 0x3f, 0xda, 0x9f, 0x05, 0x5f, 0x86, - 0x60, 0x19, 0x88, 0x8f, 0xd1, 0x14, 0x95, 0x1d, 0xed, 0x82, 0x79, 0xeb, 0xd0, 0x98, 0x87, 0x01, - 0x6a, 0x4f, 0x0f, 0x73, 0x79, 0xdf, 0xaa, 0xa2, 0xc9, 0xc7, 0xcc, 0xbf, 0x5f, 0x21, 0x67, 0x37, - 0x58, 0xcd, 0x9d, 0xae, 0x0a, 0x04, 0x1b, 0xed, 0x17, 0xec, 0xd4, 0xb7, 0x0a, 0x07, 0x0b, 0x3a, - 0x93, 0x5d, 0x44, 0x38, 0xf0, 0x67, 0x65, 0xe3, 0xf9, 0x89, 0xa5, 0x5d, 0x50, 0x87, 0x05, 0x34, - 0xc6, 0x3f, 0xd6, 0x59, 0xe4, 0xc9, 0x5c, 0x58, 0xf3, 0x7e, 0x13, 0x50, 0x66, 0xa0, 0x33, 0x54, - 0x9f, 0x42, 0x77, 0x65, 0x8b, 0x51, 0xc7, 0xb0, 0xfc, 0x0b, 0x0a, 0x8f, 0x01, 0x31, 0x1d, 0x0d, - 0x04, 0x76, 0x5f, 0x02, 0xb3, 0x5e, 0x3a, 0x67, 0xcd, 0xd4, 0x1d, 0xbe, 0x0c, 0x4f, 0xf8, 0x0c, - 0xdd, 0xeb, 0x7e, 0x9e, 0x74, 0x25, 0x69, 0x9c, 0xdf, 0x81, 0x4c, 0x6f, 0x03, 0x3a, 0xaf, 0x6b, - 0x87, 0x0a, 0xb3, 0xe8, 0x92, 0x4d, 0xda, 0x70, 0x9d, 0xf7, 0x19, 0xdf, 0xda, 0xa7, 0x0e, 0xf5, - 0xeb, 0xee, 0x82, 0x08, 0x21, 0x90, 0x0c, 0x9a, 0x76, 0x3f, 0x73, 0x3a, 0x0c, 0x80, 0x3f, 0xe5, - 0x2e, 0xfa, 0x81, 0xf1, 0x1a, 0x9a, 0xe9, 0xd2, 0x2a, 0xd4, 0xa1, 0x50, 0xcd, 0x74, 0x67, 0xd5, - 0x4d, 0x45, 0xf2, 0x70, 0xd3, 0x43, 0xe9, 0xa1, 0x73, 0x6b, 0x68, 0x46, 0x61, 0xa1, 0x10, 0x1e, - 0xc7, 0x74, 0x67, 0xd5, 0x35, 0xdf, 0xfe, 0x77, 0x1a, 0x8d, 0xf3, 0x18, 0x58, 0x47, 0x09, 0xef, - 0x93, 0x06, 0x3f, 0x8c, 0xbc, 0x12, 0xbd, 0xdf, 0x4c, 0x22, 0x19, 0x64, 0xe2, 0x11, 0x90, 0xa5, - 0x17, 0xbf, 0xff, 0xfd, 0xfd, 0xe8, 0x02, 0x9e, 0x93, 0xe2, 0x3e, 0x21, 0xf1, 0x8f, 0x02, 0x4a, - 0x06, 0x86, 0x22, 0x7e, 0x27, 0x2e, 0x64, 0xac, 0x52, 0x8b, 0xd9, 0xeb, 0x98, 0x02, 0xc5, 0x2e, - 0xa7, 0x78, 0x84, 0xb7, 0xa5, 0xfe, 0x1f, 0xab, 0x52, 0x2b, 0x38, 0xfd, 0xdb, 0x52, 0x8b, 0xcb, - 0x7a, 0x1b, 0x7f, 0x2b, 0xa0, 0x99, 0xe0, 0xdc, 0xae, 0x54, 0xe2, 0x29, 0x63, 0x45, 0x39, 0x9e, - 0x32, 0x5e, 0x58, 0x49, 0x86, 0x53, 0x2e, 0xe1, 0xfb, 0x03, 0x28, 0xf1, 0x2b, 0x01, 0xa5, 0xc2, - 0x38, 0x5d, 0x45, 0xc2, 0x3b, 0xc3, 0xb3, 0xf5, 0x68, 0xa1, 0xf8, 0xe8, 0x66, 0x4e, 0x00, 0xbb, - 0xcd, 0x61, 0xdf, 0xc5, 0xd9, 0xeb, 0xb7, 0x14, 0x7f, 0x23, 0xa0, 0xa9, 0xa0, 0x6a, 0xe1, 0x8d, - 0xb8, 0xd4, 0x31, 0x9a, 0x27, 0x6e, 0x0e, 0x37, 0x04, 0xae, 0x55, 0xce, 0x95, 0xc6, 0x0f, 0x22, - 0x5c, 0x15, 0x6e, 0x5c, 0xf4, 0xe4, 0xd0, 0x25, 0x99, 0xf0, 0x87, 0x3c, 0x5e, 0xef, 0x73, 0x93, - 0x22, 0xe2, 0x24, 0x6e, 0x0c, 0xb5, 0x03, 0x86, 0x2c, 0x67, 0x58, 0xc5, 0x44, 0xea, 0xf3, 0x97, - 0x8f, 0xd4, 0x02, 0x89, 0x6d, 0xe3, 0xaf, 0x05, 0x94, 0xf4, 0x03, 0xb8, 0x77, 0x6b, 0xbd, 0xcf, - 0x69, 0x5c, 0x0b, 0x26, 0x46, 0xed, 0xc8, 0x0a, 0x87, 0x11, 0x71, 0xaa, 0x1f, 0x0c, 0x36, 0x50, - 0x02, 0xa4, 0x21, 0xfe, 0xa5, 0x0f, 0x4a, 0x54, 0x9f, 0x97, 0x3e, 0x24, 0x57, 0x24, 0xcd, 0x53, - 0xa6, 0xf0, 0x7c, 0x34, 0x65, 0xbd, 0xe4, 0x8e, 0x3c, 0xfc, 0x42, 0x40, 0xc9, 0xc0, 0xa0, 0xc7, - 0x99, 0xb8, 0x98, 0x91, 0x3f, 0x55, 0xc4, 0xd5, 0xc1, 0x46, 0x90, 0x7a, 0x93, 0xa7, 0x26, 0x78, - 0x25, 0x92, 0xda, 0x9f, 0xb4, 0x52, 0xcb, 0x13, 0x8c, 0xb6, 0x0b, 0x31, 0x13, 0xc8, 0x31, 0xa8, - 0xf7, 0x51, 0x94, 0x8d, 0xa1, 0x76, 0x40, 0xb3, 0xcc, 0x69, 0x16, 0xf1, 0x42, 0x1f, 0x1a, 0xfc, - 0xab, 0x80, 0xe6, 0xe3, 0xd5, 0x0f, 0x6f, 0xc5, 0x25, 0x19, 0x28, 0xb3, 0xe2, 0xf6, 0x4d, 0x5c, - 0x00, 0x71, 0x8f, 0x23, 0x7e, 0x88, 0x77, 0xa5, 0x43, 0xaa, 0x59, 0xa5, 0x8a, 0x21, 0x9f, 0x47, - 0x60, 0xed, 0xb2, 0xf1, 0xbc, 0x68, 0x7a, 0x11, 0x3a, 0x8a, 0x55, 0xb4, 0x58, 0x8d, 0xf7, 0xf2, - 0x89, 0xd2, 0xc6, 0x3f, 0x09, 0x28, 0x19, 0x90, 0x9f, 0xf8, 0x3e, 0xf6, 0xca, 0x63, 0x7c, 0x1f, - 0x63, 0x74, 0x8c, 0x3c, 0xe5, 0x90, 0x8f, 0xf1, 0x61, 0x5f, 0x48, 0x10, 0x34, 0x2e, 0x72, 0x52, - 0x2b, 0x24, 0xae, 0x6d, 0xa9, 0x15, 0xd6, 0xd1, 0xf6, 0xde, 0xfe, 0xeb, 0xcb, 0xb4, 0xf0, 0xe6, - 0x32, 0x2d, 0xfc, 0x75, 0x99, 0x16, 0xbe, 0xbb, 0x4a, 0x8f, 0xbc, 0xb9, 0x4a, 0x8f, 0xfc, 0x71, - 0x95, 0x1e, 0x79, 0x96, 0x55, 0x35, 0xa7, 0x5c, 0x2f, 0xb9, 0x5f, 0x00, 0xb1, 0xb9, 0x1a, 0x3c, - 0x1b, 0xff, 0x7f, 0x43, 0x29, 0xc1, 0xff, 0xa1, 0xb0, 0xf3, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa1, 0x79, 0x33, 0x8c, 0xbb, 0x11, 0x00, 0x00, + 0xd2, 0x5f, 0x44, 0x10, 0xab, 0xed, 0x1e, 0xa0, 0xe2, 0x92, 0xd2, 0x1f, 0x2c, 0x45, 0x6c, 0x1b, + 0x0a, 0x48, 0x7b, 0x89, 0x26, 0xf6, 0xe0, 0x58, 0x4d, 0x6c, 0xc7, 0x76, 0xba, 0x09, 0x51, 0x24, + 0xb4, 0x17, 0x2e, 0x1c, 0x90, 0xb8, 0x23, 0x8e, 0x7b, 0x83, 0x1b, 0xda, 0x33, 0x1c, 0xf6, 0xb8, + 0x12, 0x17, 0x4e, 0x08, 0xb5, 0x48, 0xfc, 0x09, 0x5c, 0x91, 0xc7, 0xcf, 0x89, 0xed, 0x38, 0x49, + 0x2b, 0x7a, 0xa9, 0xea, 0x99, 0xf7, 0xe3, 0xf3, 0xde, 0x8c, 0xdf, 0xd7, 0x2d, 0x5a, 0xfc, 0x92, + 0x6a, 0x56, 0xd3, 0xd2, 0x74, 0x55, 0x32, 0x99, 0x29, 0xd5, 0xea, 0xcc, 0x6a, 0xe6, 0x4c, 0xcb, + 0x70, 0x0c, 0x3c, 0xdd, 0xd9, 0xca, 0x99, 0xcc, 0x14, 0xdf, 0xa4, 0x55, 0x4d, 0x37, 0x24, 0xfe, + 0xd3, 0xb3, 0x10, 0x67, 0x55, 0x43, 0x35, 0xf8, 0xaf, 0x92, 0xfb, 0x1b, 0xac, 0x3e, 0x50, 0x0d, + 0x43, 0xad, 0x30, 0x89, 0x9a, 0x9a, 0x44, 0x75, 0xdd, 0x70, 0xa8, 0xa3, 0x19, 0xba, 0x0d, 0xbb, + 0x59, 0xd9, 0xb0, 0xab, 0x86, 0x2d, 0x95, 0xa8, 0xcd, 0xbc, 0x74, 0xd2, 0xc5, 0x56, 0x89, 0x39, + 0x74, 0x4b, 0x32, 0xa9, 0xaa, 0xe9, 0xdc, 0x18, 0x6c, 0xc5, 0x30, 0x9c, 0x49, 0x2d, 0x5a, 0xf5, + 0xe3, 0xac, 0x84, 0xf7, 0x98, 0x2e, 0x5b, 0x4d, 0xd3, 0x61, 0x4a, 0xd1, 0x69, 0x80, 0xc5, 0x52, + 0xc4, 0x9b, 0x99, 0x45, 0xdd, 0xd0, 0x65, 0x06, 0xdb, 0x9b, 0xe1, 0x6d, 0xaa, 0xaa, 0x16, 0x53, + 0xa9, 0x1b, 0xe1, 0x9c, 0x35, 0x8b, 0x76, 0x99, 0x5a, 0xbe, 0x65, 0xa6, 0x6b, 0x29, 0x1b, 0xd5, + 0xaa, 0xa1, 0x4b, 0x7c, 0x57, 0x29, 0x3a, 0x4d, 0x93, 0xf9, 0x3c, 0xe9, 0x60, 0x5d, 0x7e, 0x45, + 0xb2, 0xa1, 0x41, 0x2d, 0x64, 0x16, 0xe1, 0x53, 0xb7, 0xda, 0x13, 0x5e, 0x44, 0x81, 0xd5, 0xea, + 0xcc, 0x76, 0xc8, 0x13, 0x74, 0x2f, 0xb4, 0x6a, 0x9b, 0x86, 0x6e, 0x33, 0xfc, 0x2e, 0x4a, 0x78, + 0xc5, 0xa6, 0x84, 0x15, 0x61, 0x33, 0xb9, 0x3d, 0x97, 0x0b, 0x9d, 0x45, 0xce, 0x33, 0xdf, 0x9b, + 0x7c, 0xf5, 0xe7, 0xf2, 0xc8, 0x8b, 0x7f, 0x7e, 0xce, 0x0a, 0x05, 0xb0, 0x27, 0xef, 0xa0, 0x59, + 0x1e, 0xf0, 0x98, 0x35, 0x39, 0x24, 0x24, 0xc2, 0x73, 0x28, 0x61, 0xb1, 0x5a, 0x51, 0x53, 0x78, + 0xc4, 0xc9, 0xc2, 0xb8, 0xc5, 0x6a, 0x8f, 0x15, 0xf2, 0x14, 0xcd, 0x45, 0xcc, 0x81, 0x20, 0x8f, + 0x26, 0xce, 0x61, 0x0d, 0x18, 0xd6, 0x22, 0x0c, 0x47, 0x4c, 0x3f, 0xd0, 0xe5, 0xb3, 0xc6, 0x41, + 0x83, 0xc9, 0x75, 0xf7, 0xd0, 0x4e, 0xeb, 0xac, 0xce, 0x0a, 0x1d, 0x37, 0x42, 0xd1, 0x02, 0x8f, + 0x9d, 0xaf, 0x54, 0xa2, 0x34, 0x87, 0x08, 0x75, 0x0f, 0x1b, 0xe2, 0xaf, 0xe7, 0xbc, 0x0e, 0xe6, + 0xdc, 0x0e, 0xe6, 0xbc, 0x8b, 0x08, 0x7d, 0xcc, 0x9d, 0x50, 0xd5, 0xf7, 0x2d, 0x04, 0x3c, 0xc9, + 0x0b, 0x01, 0xa5, 0x7a, 0x73, 0x40, 0x09, 0x1f, 0xa0, 0x49, 0x9f, 0xc5, 0xed, 0xe3, 0x9d, 0xeb, + 0xd7, 0xd0, 0xf5, 0xc3, 0x47, 0x21, 0xd2, 0x51, 0x4e, 0xba, 0x31, 0x94, 0xd4, 0x23, 0x08, 0xa1, + 0x7e, 0x8e, 0x44, 0x4e, 0x7a, 0xc4, 0x9c, 0x03, 0xff, 0xae, 0x9e, 0x35, 0xfc, 0x86, 0x10, 0x34, + 0xe5, 0x50, 0x4b, 0x65, 0xce, 0x87, 0x4c, 0x53, 0xcb, 0x0e, 0x6f, 0xc9, 0x58, 0x21, 0xb4, 0x86, + 0x67, 0xd1, 0xb8, 0xa6, 0x2b, 0xac, 0xc1, 0x29, 0xc6, 0x0a, 0xde, 0x03, 0xa1, 0xe8, 0x7e, 0x6c, + 0x5c, 0x68, 0xc2, 0x1e, 0x4a, 0xb2, 0xee, 0x32, 0xb4, 0x5a, 0x8c, 0xb4, 0x21, 0xe0, 0xb8, 0x37, + 0xe6, 0xde, 0xa9, 0x42, 0xd0, 0x89, 0x28, 0x80, 0x9e, 0xaf, 0x54, 0x62, 0xd0, 0x6f, 0xeb, 0x2c, + 0x5f, 0x0a, 0x50, 0x49, 0x34, 0x0d, 0x54, 0x72, 0x8a, 0xde, 0x08, 0x40, 0xe5, 0x2d, 0x8b, 0x36, + 0xe1, 0x54, 0x97, 0xfb, 0x97, 0xc3, 0xcd, 0xa0, 0xa6, 0x1e, 0xf7, 0xdb, 0x3b, 0xdc, 0x8f, 0xd0, + 0x6a, 0x0c, 0xfa, 0xa1, 0x65, 0x54, 0xbd, 0xb3, 0xbb, 0xc1, 0x31, 0x93, 0xaf, 0xd0, 0xda, 0x90, + 0x58, 0x03, 0x1b, 0x22, 0xfc, 0x8f, 0x86, 0x10, 0x11, 0x5e, 0xa7, 0x8f, 0xa9, 0xc3, 0x6c, 0x27, + 0xc4, 0x4e, 0x76, 0xd0, 0x62, 0xcc, 0x1e, 0xb0, 0xcc, 0xa3, 0x44, 0x39, 0x58, 0x12, 0x3c, 0x91, + 0x1d, 0x98, 0x01, 0x47, 0xcc, 0x39, 0x61, 0xe6, 0x27, 0xee, 0xf8, 0xf5, 0x7b, 0x91, 0x42, 0x77, + 0xa9, 0xa2, 0x58, 0xcc, 0xb6, 0x61, 0x24, 0xf9, 0x8f, 0xe4, 0x33, 0xa0, 0x08, 0x39, 0x41, 0xa2, + 0xf7, 0xd0, 0x84, 0x09, 0x6b, 0x50, 0xec, 0x42, 0x74, 0x36, 0xc2, 0x36, 0x14, 0xd9, 0x31, 0x0f, + 0xce, 0xa3, 0x28, 0xcb, 0x6d, 0xdd, 0xe1, 0x1f, 0x02, 0xf3, 0x68, 0x08, 0xfa, 0x9d, 0x1b, 0xa0, + 0xdf, 0xde, 0x45, 0xed, 0xa8, 0x50, 0xbd, 0x74, 0xcc, 0x9a, 0xfe, 0xd1, 0xfe, 0x24, 0xf8, 0x32, + 0x04, 0xcb, 0x40, 0x7c, 0x8c, 0xa6, 0xa8, 0xec, 0x68, 0x17, 0xcc, 0x5b, 0x87, 0xc6, 0x3c, 0x0c, + 0x50, 0x7b, 0x7a, 0x98, 0xcb, 0xfb, 0x56, 0x15, 0x4d, 0x3e, 0x66, 0xfe, 0xfd, 0x0a, 0x39, 0xbb, + 0xc1, 0x6a, 0xee, 0x74, 0x55, 0x20, 0xd8, 0x68, 0xbf, 0x60, 0xa7, 0xbe, 0x55, 0x38, 0x58, 0xd0, + 0x99, 0xec, 0x22, 0xc2, 0x81, 0x3f, 0x2d, 0x1b, 0xcf, 0x4e, 0x2c, 0xed, 0x82, 0x3a, 0x2c, 0xa0, + 0x31, 0xfe, 0xb1, 0xce, 0x22, 0x4f, 0xe6, 0xc2, 0x9a, 0xf7, 0x9b, 0x80, 0x32, 0x03, 0x9d, 0xa1, + 0xfa, 0x14, 0xba, 0x2b, 0x5b, 0x8c, 0x3a, 0x86, 0xe5, 0x5f, 0x50, 0x78, 0x0c, 0x88, 0xe9, 0x68, + 0x20, 0xb0, 0xfb, 0x12, 0x98, 0xf5, 0xd2, 0x39, 0x6b, 0xa6, 0xee, 0xf0, 0x65, 0x78, 0xc2, 0x67, + 0xe8, 0x5e, 0xf7, 0xf3, 0xa4, 0x2b, 0x49, 0xe3, 0xfc, 0x0e, 0x64, 0x7a, 0x1b, 0xd0, 0x79, 0x5d, + 0x3b, 0x54, 0x98, 0x45, 0x97, 0x6c, 0xd2, 0x86, 0xeb, 0xbc, 0xcf, 0xf8, 0xd6, 0x3e, 0x75, 0xa8, + 0x5f, 0x77, 0x17, 0x44, 0x08, 0x81, 0x64, 0xd0, 0xb4, 0xfb, 0x99, 0xd3, 0x61, 0x00, 0xfc, 0x29, + 0x77, 0xd1, 0x0f, 0x8c, 0xd7, 0xd0, 0x4c, 0x97, 0x56, 0xa1, 0x0e, 0x85, 0x6a, 0xa6, 0x3b, 0xab, + 0x6e, 0x2a, 0x92, 0x87, 0x9b, 0x1e, 0x4a, 0x0f, 0x9d, 0x5b, 0x43, 0x33, 0x0a, 0x0b, 0x85, 0xf0, + 0x38, 0xa6, 0x3b, 0xab, 0xae, 0xf9, 0xf6, 0xbf, 0xd3, 0x68, 0x9c, 0xc7, 0xc0, 0x3a, 0x4a, 0x78, + 0x9f, 0x34, 0xf8, 0x61, 0xe4, 0x95, 0xe8, 0xfd, 0x66, 0x12, 0xc9, 0x20, 0x13, 0x8f, 0x80, 0x2c, + 0x3d, 0xff, 0xfd, 0xef, 0xef, 0x47, 0x17, 0xf0, 0x9c, 0x14, 0xf7, 0x09, 0x89, 0x7f, 0x14, 0x50, + 0x32, 0x30, 0x14, 0xf1, 0x5b, 0x71, 0x21, 0x63, 0x95, 0x5a, 0xcc, 0x5e, 0xc7, 0x14, 0x28, 0x76, + 0x39, 0xc5, 0x23, 0xbc, 0x2d, 0xf5, 0xff, 0x58, 0x95, 0x5a, 0xc1, 0xe9, 0xdf, 0x96, 0x5a, 0x5c, + 0xd6, 0xdb, 0xf8, 0x5b, 0x01, 0xcd, 0x04, 0xe7, 0x76, 0xa5, 0x12, 0x4f, 0x19, 0x2b, 0xca, 0xf1, + 0x94, 0xf1, 0xc2, 0x4a, 0x32, 0x9c, 0x72, 0x09, 0xdf, 0x1f, 0x40, 0x89, 0x5f, 0x0a, 0x28, 0x15, + 0xc6, 0xe9, 0x2a, 0x12, 0xde, 0x19, 0x9e, 0xad, 0x47, 0x0b, 0xc5, 0x47, 0x37, 0x73, 0x02, 0xd8, + 0x6d, 0x0e, 0xfb, 0x36, 0xce, 0x5e, 0xbf, 0xa5, 0xf8, 0x1b, 0x01, 0x4d, 0x05, 0x55, 0x0b, 0x6f, + 0xc4, 0xa5, 0x8e, 0xd1, 0x3c, 0x71, 0x73, 0xb8, 0x21, 0x70, 0xad, 0x72, 0xae, 0x34, 0x7e, 0x10, + 0xe1, 0xaa, 0x70, 0xe3, 0xa2, 0x27, 0x87, 0x2e, 0xc9, 0x84, 0x3f, 0xe4, 0xf1, 0x7a, 0x9f, 0x9b, + 0x14, 0x11, 0x27, 0x71, 0x63, 0xa8, 0x1d, 0x30, 0x64, 0x39, 0xc3, 0x2a, 0x26, 0x52, 0x9f, 0xbf, + 0x7c, 0xa4, 0x16, 0x48, 0x6c, 0x1b, 0x7f, 0x2d, 0xa0, 0xa4, 0x1f, 0xc0, 0xbd, 0x5b, 0xeb, 0x7d, + 0x4e, 0xe3, 0x5a, 0x30, 0x31, 0x6a, 0x47, 0x56, 0x38, 0x8c, 0x88, 0x53, 0xfd, 0x60, 0xb0, 0x81, + 0x12, 0x20, 0x0d, 0xf1, 0x2f, 0x7d, 0x50, 0xa2, 0xfa, 0xbc, 0xf4, 0x21, 0xb9, 0x22, 0x69, 0x9e, + 0x32, 0x85, 0xe7, 0xa3, 0x29, 0xeb, 0x25, 0x77, 0xe4, 0xe1, 0xe7, 0x02, 0x4a, 0x06, 0x06, 0x3d, + 0xce, 0xc4, 0xc5, 0x8c, 0xfc, 0xa9, 0x22, 0xae, 0x0e, 0x36, 0x82, 0xd4, 0x9b, 0x3c, 0x35, 0xc1, + 0x2b, 0x91, 0xd4, 0xfe, 0xa4, 0x95, 0x5a, 0x9e, 0x60, 0xb4, 0x5d, 0x88, 0x99, 0x40, 0x8e, 0x41, + 0xbd, 0x8f, 0xa2, 0x6c, 0x0c, 0xb5, 0x03, 0x9a, 0x65, 0x4e, 0xb3, 0x88, 0x17, 0xfa, 0xd0, 0xe0, + 0x5f, 0x05, 0x34, 0x1f, 0xaf, 0x7e, 0x78, 0x2b, 0x2e, 0xc9, 0x40, 0x99, 0x15, 0xb7, 0x6f, 0xe2, + 0x02, 0x88, 0x7b, 0x1c, 0xf1, 0x7d, 0xbc, 0x2b, 0x1d, 0x52, 0xcd, 0x2a, 0x55, 0x0c, 0xf9, 0x3c, + 0x02, 0x6b, 0x97, 0x8d, 0x67, 0x45, 0xd3, 0x8b, 0xd0, 0x51, 0xac, 0xa2, 0xc5, 0x6a, 0xbc, 0x97, + 0x8f, 0x95, 0x36, 0xfe, 0x45, 0x40, 0xc9, 0x80, 0xfc, 0xc4, 0xf7, 0xb1, 0x57, 0x1e, 0xe3, 0xfb, + 0x18, 0xa3, 0x63, 0xe4, 0x0b, 0x0e, 0x79, 0x8a, 0x9f, 0xf4, 0x85, 0x04, 0x41, 0xe3, 0x22, 0x27, + 0xb5, 0x3c, 0x99, 0x6d, 0x4b, 0xad, 0x90, 0xca, 0xb6, 0xa5, 0x56, 0x58, 0x50, 0xdb, 0x7b, 0xfb, + 0xaf, 0x2e, 0xd3, 0xc2, 0xeb, 0xcb, 0xb4, 0xf0, 0xd7, 0x65, 0x5a, 0xf8, 0xee, 0x2a, 0x3d, 0xf2, + 0xfa, 0x2a, 0x3d, 0xf2, 0xc7, 0x55, 0x7a, 0xe4, 0x69, 0x56, 0xd5, 0x9c, 0x72, 0xbd, 0xe4, 0x7e, + 0x0a, 0xc4, 0x26, 0x6d, 0xf0, 0xb4, 0xfc, 0x1f, 0x0f, 0xa5, 0x04, 0xff, 0xcf, 0xc2, 0xce, 0x7f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xe4, 0x33, 0xe3, 0x9f, 0xc4, 0x11, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pep/types/query.pb.gw.go b/x/pep/types/query.pb.gw.go index 4f915f65..2ee2d6db 100644 --- a/x/pep/types/query.pb.gw.go +++ b/x/pep/types/query.pb.gw.go @@ -487,10 +487,6 @@ func local_request_Query_ShowPrivateKeyshareReq_0(ctx context.Context, marshaler } -var ( - filter_Query_DecryptData_0 = &utilities.DoubleArray{Encoding: map[string]int{"aggr_keyshare": 0, "encrypted_data": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} -) - func request_Query_DecryptData_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDecryptDataRequest var metadata runtime.ServerMetadata @@ -502,6 +498,17 @@ func request_Query_DecryptData_0(ctx context.Context, marshaler runtime.Marshale _ = err ) + val, ok = pathParams["pubkey"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pubkey") + } + + protoReq.Pubkey, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pubkey", err) + } + val, ok = pathParams["aggr_keyshare"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "aggr_keyshare") @@ -524,13 +531,6 @@ func request_Query_DecryptData_0(ctx context.Context, marshaler runtime.Marshale return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "encrypted_data", 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_DecryptData_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := client.DecryptData(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -547,6 +547,17 @@ func local_request_Query_DecryptData_0(ctx context.Context, marshaler runtime.Ma _ = err ) + val, ok = pathParams["pubkey"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pubkey") + } + + protoReq.Pubkey, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pubkey", err) + } + val, ok = pathParams["aggr_keyshare"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "aggr_keyshare") @@ -569,13 +580,6 @@ func local_request_Query_DecryptData_0(ctx context.Context, marshaler runtime.Ma return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "encrypted_data", 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_DecryptData_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := server.DecryptData(ctx, &protoReq) return msg, metadata, err @@ -1170,7 +1174,7 @@ var ( pattern_Query_ShowPrivateKeyshareReq_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"Fairblock", "fairyring", "pep", "show_private_keyshare_req", "reqId"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DecryptData_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"Fairblock", "fairyring", "pep", "decrypt_data", "aggr_keyshare", "encrypted_data"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_DecryptData_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5, 1, 0, 4, 1, 5, 6}, []string{"Fairblock", "fairyring", "pep", "decrypt_data", "pubkey", "aggr_keyshare", "encrypted_data"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( From 9d9b6d925e12f7e3d9dafe481907162c623ea68a Mon Sep 17 00:00:00 2001 From: bowenyou Date: Tue, 1 Oct 2024 11:14:17 -0400 Subject: [PATCH 21/41] fix request encoding --- fairyring_contract/Cargo.lock | 1 + fairyring_contract/Cargo.toml | 4 +-- fairyring_contract/src/contract.rs | 49 +++++++++++++++--------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/fairyring_contract/Cargo.lock b/fairyring_contract/Cargo.lock index 9a66d06d..54121c3e 100644 --- a/fairyring_contract/Cargo.lock +++ b/fairyring_contract/Cargo.lock @@ -711,6 +711,7 @@ dependencies = [ "cw-multi-test", "cw-storage-plus", "fairblock-proto", + "prost", "schemars", "serde", "thiserror", diff --git a/fairyring_contract/Cargo.toml b/fairyring_contract/Cargo.toml index a250198a..7981e041 100644 --- a/fairyring_contract/Cargo.toml +++ b/fairyring_contract/Cargo.toml @@ -39,7 +39,7 @@ cw-storage-plus = "2.0.0" serde = { version = "1.0", features = ["derive"] } schemars = "0.8" thiserror = "1.0" -# prost = "0.13.3" # Protobuf support +prost = "0.13.3" # Protobuf support # prost-types = "0.13" # tonic = { version = "0.12.3", features = ["prost", "tls"] } fairblock-proto = { git = "https://github.com/Fairblock/fairblock-rust/", branch = "contract-callback" } @@ -48,4 +48,4 @@ fairblock-proto = { git = "https://github.com/Fairblock/fairblock-rust/", branch # tokio = "1.40.0" [dev-dependencies] -cw-multi-test = "2.0.0" \ No newline at end of file +cw-multi-test = "2.0.0" diff --git a/fairyring_contract/src/contract.rs b/fairyring_contract/src/contract.rs index 0328aac5..88aa2f6f 100644 --- a/fairyring_contract/src/contract.rs +++ b/fairyring_contract/src/contract.rs @@ -1,8 +1,12 @@ // contract.rs -use cosmwasm_std::{attr, entry_point, to_json_binary, to_json_string, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; -use crate::msg::{ExecuteContractMsg, QueryMsg, QueryResponse, InstantiateMsg}; +use crate::msg::{ExecuteContractMsg, InstantiateMsg, QueryMsg, QueryResponse}; use crate::state::STORED_DATA; +use cosmwasm_std::{ + attr, entry_point, to_json_binary, to_json_string, Binary, Deps, DepsMut, Env, MessageInfo, + Response, StdError, StdResult, +}; use fairblock_proto::fairyring::pep::QueryDecryptDataRequest; +use prost::Message; #[entry_point] pub fn execute( @@ -12,7 +16,7 @@ pub fn execute( msg: ExecuteContractMsg, ) -> StdResult { // Store the data - + // Check if identity is a non-empty string if msg.identity.trim().is_empty() { return Err(StdError::generic_err("Identity cannot be empty")); @@ -22,29 +26,22 @@ pub fn execute( let identity = msg.identity; STORED_DATA.save( - deps.storage, - &identity, - &(msg.pubkey.clone(), msg.aggr_keyshare.clone()), // Use `.clone()` to avoid moving the values + deps.storage, + &identity, + &(msg.pubkey.clone(), msg.aggr_keyshare.clone()), // Use `.clone()` to avoid moving the values )?; - + // Return a response - Ok(Response::new() - .add_attributes(vec![ - attr("action", "store_data"), - attr("identity", identity), - attr("pubkey", msg.pubkey), - attr("aggr_keyshare", msg.aggr_keyshare), - ]) - ) + Ok(Response::new().add_attributes(vec![ + attr("action", "store_data"), + attr("identity", identity), + attr("pubkey", msg.pubkey), + attr("aggr_keyshare", msg.aggr_keyshare), + ])) } - #[entry_point] -pub fn query( - deps: Deps, - _env: Env, - msg: QueryMsg, -) -> StdResult { +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::GetStoredData { identity } => { if identity.trim().is_empty() { @@ -99,7 +96,6 @@ pub fn instantiate( Ok(Response::new().add_attribute("method", "instantiate")) } - // Function to query the `DecryptData` RPC from your `pep` module pub fn query_pep_decrypt( deps: Deps, @@ -115,7 +111,10 @@ pub fn query_pep_decrypt( }; // Send the query - let raw_response: Binary = deps.querier.query_grpc("/fairyring.pep.Query/DecryptData".to_string(), to_json_binary(&request)?)?; - + let raw_response: Binary = deps.querier.query_grpc( + "/fairyring.pep.Query/DecryptData".to_string(), + Binary::new(request.encode_to_vec()), + )?; + Ok(raw_response) -} \ No newline at end of file +} From 27a18d6a8a4ba6f4b669a71a06210ef1dde48917 Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Tue, 1 Oct 2024 23:42:17 +0530 Subject: [PATCH 22/41] minor fix --- fairyring_contract/Cargo.lock | 821 +----------------- fairyring_contract/Cargo.toml | 6 +- fairyring_contract/artifacts/checksums.txt | 2 +- .../artifacts/fairyring_contract.wasm | Bin 195179 -> 202290 bytes fairyring_contract/src/contract.rs | 21 +- fairyring_contract/src/msg.rs | 23 +- 6 files changed, 35 insertions(+), 838 deletions(-) diff --git a/fairyring_contract/Cargo.lock b/fairyring_contract/Cargo.lock index 9a66d06d..59374ffb 100644 --- a/fairyring_contract/Cargo.lock +++ b/fairyring_contract/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - [[package]] name = "ahash" version = "0.8.11" @@ -162,113 +147,12 @@ dependencies = [ "rayon", ] -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "async-trait" -version = "0.1.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "axum" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" -dependencies = [ - "async-trait", - "axum-core", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 1.0.1", - "tower 0.5.1", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper 1.0.1", - "tower-layer", - "tower-service", -] - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -313,9 +197,6 @@ name = "bytes" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" -dependencies = [ - "serde", -] [[package]] name = "cfg-if" @@ -329,18 +210,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "cosmos-sdk-proto" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2f63ab112b8c8e7b8a29c891adc48f43145beb21c0bfbf562957072c1e0beb" -dependencies = [ - "prost", - "prost-types", - "tendermint-proto", - "tonic", -] - [[package]] name = "cosmwasm-core" version = "2.1.4" @@ -565,15 +434,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - [[package]] name = "derivative" version = "2.2.0" @@ -685,23 +545,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "fairblock-proto" -version = "0.1.0" -source = "git+https://github.com/Fairblock/fairblock-rust/?branch=contract-callback#3eb0f729a25389fdf68a0fba81aaa861c826d79a" -dependencies = [ - "cosmos-sdk-proto", - "prost", - "prost-types", - "tonic", -] - [[package]] name = "fairyring_contract" version = "0.1.0" @@ -710,7 +553,8 @@ dependencies = [ "cosmwasm-std", "cw-multi-test", "cw-storage-plus", - "fairblock-proto", + "prost", + "prost-types", "schemars", "serde", "thiserror", @@ -732,60 +576,6 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" -[[package]] -name = "flex-error" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" -dependencies = [ - "paste", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -808,12 +598,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "gimli" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" - [[package]] name = "group" version = "0.13.0" @@ -825,31 +609,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "h2" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap 2.5.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.13.2" @@ -869,12 +628,6 @@ dependencies = [ "allocator-api2", ] -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hex" version = "0.4.3" @@ -890,125 +643,6 @@ dependencies = [ "digest", ] -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-timeout" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" -dependencies = [ - "hyper", - "hyper-util", - "pin-project-lite", - "tokio", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" -dependencies = [ - "equivalent", - "hashbrown 0.14.5", -] - [[package]] name = "itertools" version = "0.10.5" @@ -1051,45 +685,12 @@ version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" -dependencies = [ - "hermit-abi", - "libc", - "wasi", - "windows-sys", -] - [[package]] name = "num-bigint" version = "0.4.6" @@ -1100,12 +701,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - [[package]] name = "num-integer" version = "0.1.46" @@ -1124,15 +719,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "object" -version = "0.36.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.20.1" @@ -1160,56 +746,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "portable-atomic" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "ppv-lite86" version = "0.2.20" @@ -1284,7 +826,6 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", "rand_chacha", "rand_core", ] @@ -1338,12 +879,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustc_version" version = "0.4.1" @@ -1353,12 +888,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - [[package]] name = "ryu" version = "1.0.18" @@ -1426,15 +955,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_bytes" -version = "0.11.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" -dependencies = [ - "serde", -] - [[package]] name = "serde_derive" version = "1.0.210" @@ -1490,31 +1010,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -1527,15 +1022,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "subtle-encoding" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" -dependencies = [ - "zeroize", -] - [[package]] name = "syn" version = "1.0.109" @@ -1558,34 +1044,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" - -[[package]] -name = "tendermint-proto" -version = "0.38.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed14abe3b0502a3afe21ca74ca5cdd6c7e8d326d982c26f98a394445eb31d6e" -dependencies = [ - "bytes", - "flex-error", - "prost", - "prost-types", - "serde", - "serde_bytes", - "subtle-encoding", - "time", -] - [[package]] name = "thiserror" version = "1.0.64" @@ -1606,199 +1064,6 @@ dependencies = [ "syn 2.0.79", ] -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "num-conv", - "powerfmt", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tokio" -version = "1.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "socket2", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "tokio-stream" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tonic" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" -dependencies = [ - "async-stream", - "async-trait", - "axum", - "base64", - "bytes", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-timeout", - "hyper-util", - "percent-encoding", - "pin-project", - "prost", - "socket2", - "tokio", - "tokio-stream", - "tower 0.4.13", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "indexmap 1.9.3", - "pin-project", - "pin-project-lite", - "rand", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper 0.1.2", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "typenum" version = "1.17.0" @@ -1823,94 +1088,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "zerocopy" version = "0.7.35" diff --git a/fairyring_contract/Cargo.toml b/fairyring_contract/Cargo.toml index a250198a..4a5fa2c0 100644 --- a/fairyring_contract/Cargo.toml +++ b/fairyring_contract/Cargo.toml @@ -39,10 +39,10 @@ cw-storage-plus = "2.0.0" serde = { version = "1.0", features = ["derive"] } schemars = "0.8" thiserror = "1.0" -# prost = "0.13.3" # Protobuf support -# prost-types = "0.13" +prost = "0.13.3" # Protobuf support +prost-types = "0.13" # tonic = { version = "0.12.3", features = ["prost", "tls"] } -fairblock-proto = { git = "https://github.com/Fairblock/fairblock-rust/", branch = "contract-callback" } +# fairblock-proto = { git = "https://github.com/Fairblock/fairblock-rust/", branch = "contract-callback" } # getrandom = { version = "0.2", features = ["js"] } # mio = "1.0.2" # tokio = "1.40.0" diff --git a/fairyring_contract/artifacts/checksums.txt b/fairyring_contract/artifacts/checksums.txt index 8591b19e..4243ee40 100644 --- a/fairyring_contract/artifacts/checksums.txt +++ b/fairyring_contract/artifacts/checksums.txt @@ -1 +1 @@ -3c3274ea81c813cd396a2536e81ca8b899eaabba8e0529cf31a5b127190ab68b fairyring_contract.wasm +02e85f8280bdae5a3645e835fd89ae59e07cd4bb06f5958610e6c3c0d5c7d78e fairyring_contract.wasm diff --git a/fairyring_contract/artifacts/fairyring_contract.wasm b/fairyring_contract/artifacts/fairyring_contract.wasm index d759437af2ace0aa1599f58c21162caed91c397c..e440ecd6c04e30bc28477196c07a89b47037917c 100644 GIT binary patch delta 63824 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 delta 57189 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 Date: Wed, 2 Oct 2024 17:24:28 +0530 Subject: [PATCH 23/41] fix pr comments --- .gitignore | 3 +- api/fairyring/pep/request_id.pulsar.go | 252 +++++++++--------- fairyring_contract/artifacts/checksums.txt | 1 - proto/fairyring/pep/request_id.proto | 2 +- .../tests/fairyring_contract}/Cargo.lock | 0 .../tests/fairyring_contract}/Cargo.toml | 0 .../artifacts/checksums.txt | 1 + .../artifacts/fairyring_contract.wasm | Bin 202290 -> 202290 bytes .../optimized_contract.wasm | Bin .../tests/fairyring_contract}/src/contract.rs | 0 .../tests/fairyring_contract}/src/error.rs | 0 .../tests/fairyring_contract}/src/lib.rs | 0 .../tests/fairyring_contract}/src/msg.rs | 0 .../tests/fairyring_contract}/src/state.rs | 0 scripts/tests/pep.sh | 13 +- x/pep/keeper/contract.go | 10 +- x/pep/module/module.go | 24 +- x/pep/types/request_id.pb.go | 102 +++---- 18 files changed, 206 insertions(+), 202 deletions(-) delete mode 100644 fairyring_contract/artifacts/checksums.txt rename {fairyring_contract => scripts/tests/fairyring_contract}/Cargo.lock (100%) rename {fairyring_contract => scripts/tests/fairyring_contract}/Cargo.toml (100%) create mode 100644 scripts/tests/fairyring_contract/artifacts/checksums.txt rename {fairyring_contract => scripts/tests/fairyring_contract}/artifacts/fairyring_contract.wasm (99%) rename {fairyring_contract => scripts/tests/fairyring_contract}/optimized_contract.wasm (100%) rename {fairyring_contract => scripts/tests/fairyring_contract}/src/contract.rs (100%) rename {fairyring_contract => scripts/tests/fairyring_contract}/src/error.rs (100%) rename {fairyring_contract => scripts/tests/fairyring_contract}/src/lib.rs (100%) rename {fairyring_contract => scripts/tests/fairyring_contract}/src/msg.rs (100%) rename {fairyring_contract => scripts/tests/fairyring_contract}/src/state.rs (100%) diff --git a/.gitignore b/.gitignore index f625d68e..27c1acce 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ DistributedIBE/ data/ devnet_data/ github.com/ -fairyring_contract/target/ \ No newline at end of file +fairyring_contract/target/ +scripts/tests/fairyring_contract/target/ \ No newline at end of file diff --git a/api/fairyring/pep/request_id.pulsar.go b/api/fairyring/pep/request_id.pulsar.go index 68c3b636..ecc62c54 100644 --- a/api/fairyring/pep/request_id.pulsar.go +++ b/api/fairyring/pep/request_id.pulsar.go @@ -1668,79 +1668,79 @@ func (x *fastReflection_ContractDetails) ProtoMethods() *protoiface.Methods { } } -var _ protoreflect.List = (*_RegisterdContract_2_list)(nil) +var _ protoreflect.List = (*_RegisteredContract_2_list)(nil) -type _RegisterdContract_2_list struct { +type _RegisteredContract_2_list struct { list *[]*ContractDetails } -func (x *_RegisterdContract_2_list) Len() int { +func (x *_RegisteredContract_2_list) Len() int { if x.list == nil { return 0 } return len(*x.list) } -func (x *_RegisterdContract_2_list) Get(i int) protoreflect.Value { +func (x *_RegisteredContract_2_list) Get(i int) protoreflect.Value { return protoreflect.ValueOfMessage((*x.list)[i].ProtoReflect()) } -func (x *_RegisterdContract_2_list) Set(i int, value protoreflect.Value) { +func (x *_RegisteredContract_2_list) Set(i int, value protoreflect.Value) { valueUnwrapped := value.Message() concreteValue := valueUnwrapped.Interface().(*ContractDetails) (*x.list)[i] = concreteValue } -func (x *_RegisterdContract_2_list) Append(value protoreflect.Value) { +func (x *_RegisteredContract_2_list) Append(value protoreflect.Value) { valueUnwrapped := value.Message() concreteValue := valueUnwrapped.Interface().(*ContractDetails) *x.list = append(*x.list, concreteValue) } -func (x *_RegisterdContract_2_list) AppendMutable() protoreflect.Value { +func (x *_RegisteredContract_2_list) AppendMutable() protoreflect.Value { v := new(ContractDetails) *x.list = append(*x.list, v) return protoreflect.ValueOfMessage(v.ProtoReflect()) } -func (x *_RegisterdContract_2_list) Truncate(n int) { +func (x *_RegisteredContract_2_list) Truncate(n int) { for i := n; i < len(*x.list); i++ { (*x.list)[i] = nil } *x.list = (*x.list)[:n] } -func (x *_RegisterdContract_2_list) NewElement() protoreflect.Value { +func (x *_RegisteredContract_2_list) NewElement() protoreflect.Value { v := new(ContractDetails) return protoreflect.ValueOfMessage(v.ProtoReflect()) } -func (x *_RegisterdContract_2_list) IsValid() bool { +func (x *_RegisteredContract_2_list) IsValid() bool { return x.list != nil } var ( - md_RegisterdContract protoreflect.MessageDescriptor - fd_RegisterdContract_identity protoreflect.FieldDescriptor - fd_RegisterdContract_contracts protoreflect.FieldDescriptor + md_RegisteredContract protoreflect.MessageDescriptor + fd_RegisteredContract_identity protoreflect.FieldDescriptor + fd_RegisteredContract_contracts protoreflect.FieldDescriptor ) func init() { file_fairyring_pep_request_id_proto_init() - md_RegisterdContract = File_fairyring_pep_request_id_proto.Messages().ByName("RegisterdContract") - fd_RegisterdContract_identity = md_RegisterdContract.Fields().ByName("identity") - fd_RegisterdContract_contracts = md_RegisterdContract.Fields().ByName("contracts") + md_RegisteredContract = File_fairyring_pep_request_id_proto.Messages().ByName("RegisteredContract") + fd_RegisteredContract_identity = md_RegisteredContract.Fields().ByName("identity") + fd_RegisteredContract_contracts = md_RegisteredContract.Fields().ByName("contracts") } -var _ protoreflect.Message = (*fastReflection_RegisterdContract)(nil) +var _ protoreflect.Message = (*fastReflection_RegisteredContract)(nil) -type fastReflection_RegisterdContract RegisterdContract +type fastReflection_RegisteredContract RegisteredContract -func (x *RegisterdContract) ProtoReflect() protoreflect.Message { - return (*fastReflection_RegisterdContract)(x) +func (x *RegisteredContract) ProtoReflect() protoreflect.Message { + return (*fastReflection_RegisteredContract)(x) } -func (x *RegisterdContract) slowProtoReflect() protoreflect.Message { +func (x *RegisteredContract) slowProtoReflect() protoreflect.Message { mi := &file_fairyring_pep_request_id_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1752,43 +1752,43 @@ func (x *RegisterdContract) slowProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -var _fastReflection_RegisterdContract_messageType fastReflection_RegisterdContract_messageType -var _ protoreflect.MessageType = fastReflection_RegisterdContract_messageType{} +var _fastReflection_RegisteredContract_messageType fastReflection_RegisteredContract_messageType +var _ protoreflect.MessageType = fastReflection_RegisteredContract_messageType{} -type fastReflection_RegisterdContract_messageType struct{} +type fastReflection_RegisteredContract_messageType struct{} -func (x fastReflection_RegisterdContract_messageType) Zero() protoreflect.Message { - return (*fastReflection_RegisterdContract)(nil) +func (x fastReflection_RegisteredContract_messageType) Zero() protoreflect.Message { + return (*fastReflection_RegisteredContract)(nil) } -func (x fastReflection_RegisterdContract_messageType) New() protoreflect.Message { - return new(fastReflection_RegisterdContract) +func (x fastReflection_RegisteredContract_messageType) New() protoreflect.Message { + return new(fastReflection_RegisteredContract) } -func (x fastReflection_RegisterdContract_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_RegisterdContract +func (x fastReflection_RegisteredContract_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_RegisteredContract } // Descriptor returns message descriptor, which contains only the protobuf // type information for the message. -func (x *fastReflection_RegisterdContract) Descriptor() protoreflect.MessageDescriptor { - return md_RegisterdContract +func (x *fastReflection_RegisteredContract) Descriptor() protoreflect.MessageDescriptor { + return md_RegisteredContract } // Type returns the message type, which encapsulates both Go and protobuf // type information. If the Go type information is not needed, // it is recommended that the message descriptor be used instead. -func (x *fastReflection_RegisterdContract) Type() protoreflect.MessageType { - return _fastReflection_RegisterdContract_messageType +func (x *fastReflection_RegisteredContract) Type() protoreflect.MessageType { + return _fastReflection_RegisteredContract_messageType } // New returns a newly allocated and mutable empty message. -func (x *fastReflection_RegisterdContract) New() protoreflect.Message { - return new(fastReflection_RegisterdContract) +func (x *fastReflection_RegisteredContract) New() protoreflect.Message { + return new(fastReflection_RegisteredContract) } // Interface unwraps the message reflection interface and // returns the underlying ProtoMessage interface. -func (x *fastReflection_RegisterdContract) Interface() protoreflect.ProtoMessage { - return (*RegisterdContract)(x) +func (x *fastReflection_RegisteredContract) Interface() protoreflect.ProtoMessage { + return (*RegisteredContract)(x) } // Range iterates over every populated field in an undefined order, @@ -1796,16 +1796,16 @@ func (x *fastReflection_RegisterdContract) Interface() protoreflect.ProtoMessage // Range returns immediately if f returns false. // While iterating, mutating operations may only be performed // on the current field descriptor. -func (x *fastReflection_RegisterdContract) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { +func (x *fastReflection_RegisteredContract) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { if x.Identity != "" { value := protoreflect.ValueOfString(x.Identity) - if !f(fd_RegisterdContract_identity, value) { + if !f(fd_RegisteredContract_identity, value) { return } } if len(x.Contracts) != 0 { - value := protoreflect.ValueOfList(&_RegisterdContract_2_list{list: &x.Contracts}) - if !f(fd_RegisterdContract_contracts, value) { + value := protoreflect.ValueOfList(&_RegisteredContract_2_list{list: &x.Contracts}) + if !f(fd_RegisteredContract_contracts, value) { return } } @@ -1822,17 +1822,17 @@ func (x *fastReflection_RegisterdContract) Range(f func(protoreflect.FieldDescri // In other cases (aside from the nullable cases above), // a proto3 scalar field is populated if it contains a non-zero value, and // a repeated field is populated if it is non-empty. -func (x *fastReflection_RegisterdContract) Has(fd protoreflect.FieldDescriptor) bool { +func (x *fastReflection_RegisteredContract) Has(fd protoreflect.FieldDescriptor) bool { switch fd.FullName() { - case "fairyring.pep.RegisterdContract.identity": + case "fairyring.pep.RegisteredContract.identity": return x.Identity != "" - case "fairyring.pep.RegisterdContract.contracts": + case "fairyring.pep.RegisteredContract.contracts": return len(x.Contracts) != 0 default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisteredContract")) } - panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message fairyring.pep.RegisteredContract does not contain field %s", fd.FullName())) } } @@ -1842,17 +1842,17 @@ func (x *fastReflection_RegisterdContract) Has(fd protoreflect.FieldDescriptor) // associated with the given field number. // // Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_RegisterdContract) Clear(fd protoreflect.FieldDescriptor) { +func (x *fastReflection_RegisteredContract) Clear(fd protoreflect.FieldDescriptor) { switch fd.FullName() { - case "fairyring.pep.RegisterdContract.identity": + case "fairyring.pep.RegisteredContract.identity": x.Identity = "" - case "fairyring.pep.RegisterdContract.contracts": + case "fairyring.pep.RegisteredContract.contracts": x.Contracts = nil default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisteredContract")) } - panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message fairyring.pep.RegisteredContract does not contain field %s", fd.FullName())) } } @@ -1862,22 +1862,22 @@ func (x *fastReflection_RegisterdContract) Clear(fd protoreflect.FieldDescriptor // the default value of a bytes scalar is guaranteed to be a copy. // For unpopulated composite types, it returns an empty, read-only view // of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_RegisterdContract) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_RegisteredContract) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { switch descriptor.FullName() { - case "fairyring.pep.RegisterdContract.identity": + case "fairyring.pep.RegisteredContract.identity": value := x.Identity return protoreflect.ValueOfString(value) - case "fairyring.pep.RegisterdContract.contracts": + case "fairyring.pep.RegisteredContract.contracts": if len(x.Contracts) == 0 { - return protoreflect.ValueOfList(&_RegisterdContract_2_list{}) + return protoreflect.ValueOfList(&_RegisteredContract_2_list{}) } - listValue := &_RegisterdContract_2_list{list: &x.Contracts} + listValue := &_RegisteredContract_2_list{list: &x.Contracts} return protoreflect.ValueOfList(listValue) default: if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisteredContract")) } - panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", descriptor.FullName())) + panic(fmt.Errorf("message fairyring.pep.RegisteredContract does not contain field %s", descriptor.FullName())) } } @@ -1891,19 +1891,19 @@ func (x *fastReflection_RegisterdContract) Get(descriptor protoreflect.FieldDesc // empty, read-only value, then it panics. // // Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_RegisterdContract) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { +func (x *fastReflection_RegisteredContract) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { switch fd.FullName() { - case "fairyring.pep.RegisterdContract.identity": + case "fairyring.pep.RegisteredContract.identity": x.Identity = value.Interface().(string) - case "fairyring.pep.RegisterdContract.contracts": + case "fairyring.pep.RegisteredContract.contracts": lv := value.List() - clv := lv.(*_RegisterdContract_2_list) + clv := lv.(*_RegisteredContract_2_list) x.Contracts = *clv.list default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisteredContract")) } - panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message fairyring.pep.RegisteredContract does not contain field %s", fd.FullName())) } } @@ -1917,49 +1917,49 @@ func (x *fastReflection_RegisterdContract) Set(fd protoreflect.FieldDescriptor, // It panics if the field does not contain a composite type. // // Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_RegisterdContract) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_RegisteredContract) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "fairyring.pep.RegisterdContract.contracts": + case "fairyring.pep.RegisteredContract.contracts": if x.Contracts == nil { x.Contracts = []*ContractDetails{} } - value := &_RegisterdContract_2_list{list: &x.Contracts} + value := &_RegisteredContract_2_list{list: &x.Contracts} return protoreflect.ValueOfList(value) - case "fairyring.pep.RegisterdContract.identity": - panic(fmt.Errorf("field identity of message fairyring.pep.RegisterdContract is not mutable")) + case "fairyring.pep.RegisteredContract.identity": + panic(fmt.Errorf("field identity of message fairyring.pep.RegisteredContract is not mutable")) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisteredContract")) } - panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message fairyring.pep.RegisteredContract does not contain field %s", fd.FullName())) } } // NewField returns a new value that is assignable to the field // for the given descriptor. For scalars, this returns the default value. // For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_RegisterdContract) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_RegisteredContract) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "fairyring.pep.RegisterdContract.identity": + case "fairyring.pep.RegisteredContract.identity": return protoreflect.ValueOfString("") - case "fairyring.pep.RegisterdContract.contracts": + case "fairyring.pep.RegisteredContract.contracts": list := []*ContractDetails{} - return protoreflect.ValueOfList(&_RegisterdContract_2_list{list: &list}) + return protoreflect.ValueOfList(&_RegisteredContract_2_list{list: &list}) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisterdContract")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.RegisteredContract")) } - panic(fmt.Errorf("message fairyring.pep.RegisterdContract does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message fairyring.pep.RegisteredContract does not contain field %s", fd.FullName())) } } // WhichOneof reports which field within the oneof is populated, // returning nil if none are populated. // It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_RegisterdContract) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { +func (x *fastReflection_RegisteredContract) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { switch d.FullName() { default: - panic(fmt.Errorf("%s is not a oneof field in fairyring.pep.RegisterdContract", d.FullName())) + panic(fmt.Errorf("%s is not a oneof field in fairyring.pep.RegisteredContract", d.FullName())) } panic("unreachable") } @@ -1967,7 +1967,7 @@ func (x *fastReflection_RegisterdContract) WhichOneof(d protoreflect.OneofDescri // GetUnknown retrieves the entire list of unknown fields. // The caller may only mutate the contents of the RawFields // if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_RegisterdContract) GetUnknown() protoreflect.RawFields { +func (x *fastReflection_RegisteredContract) GetUnknown() protoreflect.RawFields { return x.unknownFields } @@ -1978,7 +1978,7 @@ func (x *fastReflection_RegisterdContract) GetUnknown() protoreflect.RawFields { // An empty RawFields may be passed to clear the fields. // // SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_RegisterdContract) SetUnknown(fields protoreflect.RawFields) { +func (x *fastReflection_RegisteredContract) SetUnknown(fields protoreflect.RawFields) { x.unknownFields = fields } @@ -1990,7 +1990,7 @@ func (x *fastReflection_RegisterdContract) SetUnknown(fields protoreflect.RawFie // message type, but the details are implementation dependent. // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. -func (x *fastReflection_RegisterdContract) IsValid() bool { +func (x *fastReflection_RegisteredContract) IsValid() bool { return x != nil } @@ -2000,9 +2000,9 @@ func (x *fastReflection_RegisterdContract) IsValid() bool { // The returned methods type is identical to // "google.golang.org/protobuf/runtime/protoiface".Methods. // Consult the protoiface package documentation for details. -func (x *fastReflection_RegisterdContract) ProtoMethods() *protoiface.Methods { +func (x *fastReflection_RegisteredContract) ProtoMethods() *protoiface.Methods { size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*RegisterdContract) + x := input.Message.Interface().(*RegisteredContract) if x == nil { return protoiface.SizeOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -2034,7 +2034,7 @@ func (x *fastReflection_RegisterdContract) ProtoMethods() *protoiface.Methods { } marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*RegisterdContract) + x := input.Message.Interface().(*RegisteredContract) if x == nil { return protoiface.MarshalOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -2087,7 +2087,7 @@ func (x *fastReflection_RegisterdContract) ProtoMethods() *protoiface.Methods { }, nil } unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*RegisterdContract) + x := input.Message.Interface().(*RegisteredContract) if x == nil { return protoiface.UnmarshalOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -2119,10 +2119,10 @@ func (x *fastReflection_RegisterdContract) ProtoMethods() *protoiface.Methods { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: RegisterdContract: wiretype end group for non-group") + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: RegisteredContract: wiretype end group for non-group") } if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: RegisterdContract: illegal tag %d (wire type %d)", fieldNum, wire) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: RegisteredContract: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -2932,7 +2932,7 @@ func (x *ContractDetails) GetContractAddress() string { return "" } -type RegisterdContract struct { +type RegisteredContract struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -2941,8 +2941,8 @@ type RegisterdContract struct { Contracts []*ContractDetails `protobuf:"bytes,2,rep,name=contracts,proto3" json:"contracts,omitempty"` } -func (x *RegisterdContract) Reset() { - *x = RegisterdContract{} +func (x *RegisteredContract) Reset() { + *x = RegisteredContract{} if protoimpl.UnsafeEnabled { mi := &file_fairyring_pep_request_id_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2950,25 +2950,25 @@ func (x *RegisterdContract) Reset() { } } -func (x *RegisterdContract) String() string { +func (x *RegisteredContract) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RegisterdContract) ProtoMessage() {} +func (*RegisteredContract) ProtoMessage() {} -// Deprecated: Use RegisterdContract.ProtoReflect.Descriptor instead. -func (*RegisterdContract) Descriptor() ([]byte, []int) { +// Deprecated: Use RegisteredContract.ProtoReflect.Descriptor instead. +func (*RegisteredContract) Descriptor() ([]byte, []int) { return file_fairyring_pep_request_id_proto_rawDescGZIP(), []int{3} } -func (x *RegisterdContract) GetIdentity() string { +func (x *RegisteredContract) GetIdentity() string { if x != nil { return x.Identity } return "" } -func (x *RegisterdContract) GetContracts() []*ContractDetails { +func (x *RegisteredContract) GetContracts() []*ContractDetails { if x != nil { return x.Contracts } @@ -3056,31 +3056,31 @@ var file_fairyring_pep_request_id_proto_rawDesc = []byte{ 0x09, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x6d, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x61, 0x63, 0x74, 0x73, 0x22, 0x6d, 0x0a, 0x12, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x4d, 0x73, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, - 0x0a, 0x0d, 0x61, 0x67, 0x67, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x67, 0x67, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x68, - 0x61, 0x72, 0x65, 0x42, 0x98, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x42, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x49, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x61, - 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0xa2, 0x02, 0x03, 0x46, 0x50, - 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, - 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, - 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, - 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, - 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x50, 0x65, 0x70, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x6e, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x66, 0x61, 0x69, + 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x73, 0x22, 0x6d, 0x0a, 0x12, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x4d, 0x73, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, + 0x23, 0x0a, 0x0d, 0x61, 0x67, 0x67, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x67, 0x67, 0x72, 0x4b, 0x65, 0x79, 0x73, + 0x68, 0x61, 0x72, 0x65, 0x42, 0x98, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x61, 0x69, + 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x42, 0x0e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x49, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, + 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0xa2, 0x02, 0x03, 0x46, + 0x50, 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, + 0x65, 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, + 0x65, 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, + 0x65, 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x0e, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x50, 0x65, 0x70, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3100,13 +3100,13 @@ var file_fairyring_pep_request_id_proto_goTypes = []interface{}{ (*RequestId)(nil), // 0: fairyring.pep.RequestId (*PrivateRequest)(nil), // 1: fairyring.pep.PrivateRequest (*ContractDetails)(nil), // 2: fairyring.pep.ContractDetails - (*RegisterdContract)(nil), // 3: fairyring.pep.RegisterdContract + (*RegisteredContract)(nil), // 3: fairyring.pep.RegisteredContract (*ExecuteContractMsg)(nil), // 4: fairyring.pep.ExecuteContractMsg (*common.EncryptedKeyshare)(nil), // 5: fairyring.common.EncryptedKeyshare } var file_fairyring_pep_request_id_proto_depIdxs = []int32{ 5, // 0: fairyring.pep.PrivateRequest.encrypted_keyshares:type_name -> fairyring.common.EncryptedKeyshare - 2, // 1: fairyring.pep.RegisterdContract.contracts:type_name -> fairyring.pep.ContractDetails + 2, // 1: fairyring.pep.RegisteredContract.contracts:type_name -> fairyring.pep.ContractDetails 2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name @@ -3157,7 +3157,7 @@ func file_fairyring_pep_request_id_proto_init() { } } file_fairyring_pep_request_id_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterdContract); i { + switch v := v.(*RegisteredContract); i { case 0: return &v.state case 1: diff --git a/fairyring_contract/artifacts/checksums.txt b/fairyring_contract/artifacts/checksums.txt deleted file mode 100644 index 4243ee40..00000000 --- a/fairyring_contract/artifacts/checksums.txt +++ /dev/null @@ -1 +0,0 @@ -02e85f8280bdae5a3645e835fd89ae59e07cd4bb06f5958610e6c3c0d5c7d78e fairyring_contract.wasm diff --git a/proto/fairyring/pep/request_id.proto b/proto/fairyring/pep/request_id.proto index c5446fb5..fd04d48c 100644 --- a/proto/fairyring/pep/request_id.proto +++ b/proto/fairyring/pep/request_id.proto @@ -23,7 +23,7 @@ message ContractDetails { string contract_address = 2; } -message RegisterdContract { +message RegisteredContract { string identity = 1; repeated ContractDetails contracts = 2; } diff --git a/fairyring_contract/Cargo.lock b/scripts/tests/fairyring_contract/Cargo.lock similarity index 100% rename from fairyring_contract/Cargo.lock rename to scripts/tests/fairyring_contract/Cargo.lock diff --git a/fairyring_contract/Cargo.toml b/scripts/tests/fairyring_contract/Cargo.toml similarity index 100% rename from fairyring_contract/Cargo.toml rename to scripts/tests/fairyring_contract/Cargo.toml diff --git a/scripts/tests/fairyring_contract/artifacts/checksums.txt b/scripts/tests/fairyring_contract/artifacts/checksums.txt new file mode 100644 index 00000000..7b54131d --- /dev/null +++ b/scripts/tests/fairyring_contract/artifacts/checksums.txt @@ -0,0 +1 @@ +c935c52c556a28243a4c11f4bf94aedac9313df501e59538b79eb82de5e592a1 fairyring_contract.wasm diff --git a/fairyring_contract/artifacts/fairyring_contract.wasm b/scripts/tests/fairyring_contract/artifacts/fairyring_contract.wasm similarity index 99% rename from fairyring_contract/artifacts/fairyring_contract.wasm rename to scripts/tests/fairyring_contract/artifacts/fairyring_contract.wasm index e440ecd6c04e30bc28477196c07a89b47037917c..e850ccefdcd39767e061680af871635670dc2f26 100644 GIT binary patch delta 21 dcmdnAhG)|no`x32Elf^V7)!T1UtxOh2mobI2^;_b delta 21 dcmdnAhG)|no`x32Elf^V80)q>UtxOh2mob{2_*mk diff --git a/fairyring_contract/optimized_contract.wasm b/scripts/tests/fairyring_contract/optimized_contract.wasm similarity index 100% rename from fairyring_contract/optimized_contract.wasm rename to scripts/tests/fairyring_contract/optimized_contract.wasm diff --git a/fairyring_contract/src/contract.rs b/scripts/tests/fairyring_contract/src/contract.rs similarity index 100% rename from fairyring_contract/src/contract.rs rename to scripts/tests/fairyring_contract/src/contract.rs diff --git a/fairyring_contract/src/error.rs b/scripts/tests/fairyring_contract/src/error.rs similarity index 100% rename from fairyring_contract/src/error.rs rename to scripts/tests/fairyring_contract/src/error.rs diff --git a/fairyring_contract/src/lib.rs b/scripts/tests/fairyring_contract/src/lib.rs similarity index 100% rename from fairyring_contract/src/lib.rs rename to scripts/tests/fairyring_contract/src/lib.rs diff --git a/fairyring_contract/src/msg.rs b/scripts/tests/fairyring_contract/src/msg.rs similarity index 100% rename from fairyring_contract/src/msg.rs rename to scripts/tests/fairyring_contract/src/msg.rs diff --git a/fairyring_contract/src/state.rs b/scripts/tests/fairyring_contract/src/state.rs similarity index 100% rename from fairyring_contract/src/state.rs rename to scripts/tests/fairyring_contract/src/state.rs diff --git a/scripts/tests/pep.sh b/scripts/tests/pep.sh index 63090280..01be7002 100755 --- a/scripts/tests/pep.sh +++ b/scripts/tests/pep.sh @@ -15,7 +15,7 @@ echo "" BINARY=fairyringd CHAIN_DIR=$(pwd)/data -CONTRACT_DIR=$(pwd)/fairyring_contract +CONTRACT_DIR=$(pwd)/scripts/tests/fairyring_contract CHAINID_1=fairyring_test_1 CHAIN1_NODE=tcp://localhost:16657 CHAINID_2=fairyring_test_2 @@ -876,13 +876,18 @@ echo "Query Contract state" RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"get_stored_data":{"identity": "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/contract123"}}' --node $CHAIN1_NODE -o json) echo $RSP -echo "#############################################" -echo "# Testing contract callback on source chain #" -echo "#############################################" +echo "#########################################################" +echo "# Testing decryption from contract request source chain #" +echo "#########################################################" +echo "Testing with pubkey provided explicitly" RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"decrypt_data": {"pubkey": "a2a4472488440341db3252447af1c31e06fd32d7067e300ed60052fcdd131fd702bf901e1dd0122a312bb582a9a375a3", "aggr_keyshare": "a3b49bbffd655aa37e0b71a4d90862e1f70bdd0aab48587307ef74c2b3e12fd2ea42d88fc5f592e5caf83d33d7f93454196f32137817ceb5ecb41fbe48c3734bb11510febd6988302dd2c362deb3479b4946daa399fb149e63c0a5c45b48292d", "encrypted_data": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20646973744942450a686e4a7641376d5655797679397166465230447849417464374c3152586371484542687736306a316f325a446e567453626a4759374a4d2f5a524752654e536b0a574d6f56567966674d55546f363944502f4f624a6544424e6f47694b50746a6b316a523075464276536372326d766948543238524f6e473755647835683077510a6c734767656554424336786e7834626e496d737874410a2d2d2d20793668724135506e5233563568414a35646f732b574e325932334b72742b383946306d4d743138595a59490a43129dfd9ddbb210374314a96ab1b06260b4e1abf7d3fac77029043c8bdbe0a6efd2b73f95f75be0"}}' --node $CHAIN1_NODE -o json) echo $RSP +echo "Testing with pubkey not provided" +RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"decrypt_data": {"pubkey": "", "aggr_keyshare": "a3b49bbffd655aa37e0b71a4d90862e1f70bdd0aab48587307ef74c2b3e12fd2ea42d88fc5f592e5caf83d33d7f93454196f32137817ceb5ecb41fbe48c3734bb11510febd6988302dd2c362deb3479b4946daa399fb149e63c0a5c45b48292d", "encrypted_data": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20646973744942450a686e4a7641376d5655797679397166465230447849417464374c3152586371484542687736306a316f325a446e567453626a4759374a4d2f5a524752654e536b0a574d6f56567966674d55546f363944502f4f624a6544424e6f47694b50746a6b316a523075464276536372326d766948543238524f6e473755647835683077510a6c734767656554424336786e7834626e496d737874410a2d2d2d20793668724135506e5233563568414a35646f732b574e325932334b72742b383946306d4d743138595a59490a43129dfd9ddbb210374314a96ab1b06260b4e1abf7d3fac77029043c8bdbe0a6efd2b73f95f75be0"}}' --node $CHAIN1_NODE -o json) +echo $RSP + echo "" echo "###########################################################" echo "# SUCCESSFULLY TESTED #" diff --git a/x/pep/keeper/contract.go b/x/pep/keeper/contract.go index 1efd87c7..8d5a736c 100644 --- a/x/pep/keeper/contract.go +++ b/x/pep/keeper/contract.go @@ -14,7 +14,7 @@ import ( ) // SetContractEntry set a specific contract entry in the store by identity -func (k Keeper) SetContractEntry(ctx context.Context, contract types.RegisterdContract) { +func (k Keeper) SetContractEntry(ctx context.Context, contract types.RegisteredContract) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.ContractKeyPrefix)) b := k.cdc.MustMarshal(&contract) @@ -25,7 +25,7 @@ func (k Keeper) SetContractEntry(ctx context.Context, contract types.RegisterdCo func (k Keeper) GetContractEntriesByID( ctx context.Context, identity string, -) (val types.RegisterdContract, found bool) { +) (val types.RegisteredContract, found bool) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.ContractKeyPrefix)) @@ -61,7 +61,7 @@ func (k Keeper) GetContractEntry( // AppendContractToEntry appends a new contract detail to an already existing contract entry func (k Keeper) AppendContractToEntry( ctx context.Context, - contract types.RegisterdContract, + contract types.RegisteredContract, ) { c, found := k.GetContractEntriesByID(ctx, contract.Identity) if !found { @@ -73,7 +73,7 @@ func (k Keeper) AppendContractToEntry( } // GetAllContractEntries returns all contracts for all identities -func (k Keeper) GetAllContractEntries(ctx context.Context) (list []types.RegisterdContract) { +func (k Keeper) GetAllContractEntries(ctx context.Context) (list []types.RegisteredContract) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.ContractKeyPrefix)) iterator := storetypes.KVStorePrefixIterator(store, []byte{}) @@ -81,7 +81,7 @@ func (k Keeper) GetAllContractEntries(ctx context.Context) (list []types.Registe defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - var val types.RegisterdContract + var val types.RegisteredContract k.cdc.MustUnmarshal(iterator.Value(), &val) list = append(list, val) } diff --git a/x/pep/module/module.go b/x/pep/module/module.go index d6caaa7a..86bcb902 100644 --- a/x/pep/module/module.go +++ b/x/pep/module/module.go @@ -279,19 +279,17 @@ func (am AppModule) BeginBlock(cctx context.Context) error { // execute registered contracts contracts, found := am.keeper.GetContractEntriesByID(ctx, entry.Identity) - if found { - if len(contracts.Contracts) != 0 { - for _, contract := range contracts.Contracts { - am.keeper.ExecuteContract( - ctx, - contract.ContractAddress, - types.ExecuteContractMsg{ - Identity: entry.Identity, - Pubkey: entry.Pubkey, - AggrKeyshare: entry.AggrKeyshare, - }, - ) - } + if found && len(contracts.Contracts) != 0 { + for _, contract := range contracts.Contracts { + am.keeper.ExecuteContract( + ctx, + contract.ContractAddress, + types.ExecuteContractMsg{ + Identity: entry.Identity, + Pubkey: entry.Pubkey, + AggrKeyshare: entry.AggrKeyshare, + }, + ) } } diff --git a/x/pep/types/request_id.pb.go b/x/pep/types/request_id.pb.go index 8d35b714..33576192 100644 --- a/x/pep/types/request_id.pb.go +++ b/x/pep/types/request_id.pb.go @@ -196,23 +196,23 @@ func (m *ContractDetails) GetContractAddress() string { return "" } -type RegisterdContract struct { +type RegisteredContract struct { Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` Contracts []*ContractDetails `protobuf:"bytes,2,rep,name=contracts,proto3" json:"contracts,omitempty"` } -func (m *RegisterdContract) Reset() { *m = RegisterdContract{} } -func (m *RegisterdContract) String() string { return proto.CompactTextString(m) } -func (*RegisterdContract) ProtoMessage() {} -func (*RegisterdContract) Descriptor() ([]byte, []int) { +func (m *RegisteredContract) Reset() { *m = RegisteredContract{} } +func (m *RegisteredContract) String() string { return proto.CompactTextString(m) } +func (*RegisteredContract) ProtoMessage() {} +func (*RegisteredContract) Descriptor() ([]byte, []int) { return fileDescriptor_3e457d2e8ff0411e, []int{3} } -func (m *RegisterdContract) XXX_Unmarshal(b []byte) error { +func (m *RegisteredContract) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RegisterdContract) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *RegisteredContract) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RegisterdContract.Marshal(b, m, deterministic) + return xxx_messageInfo_RegisteredContract.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -222,26 +222,26 @@ func (m *RegisterdContract) XXX_Marshal(b []byte, deterministic bool) ([]byte, e return b[:n], nil } } -func (m *RegisterdContract) XXX_Merge(src proto.Message) { - xxx_messageInfo_RegisterdContract.Merge(m, src) +func (m *RegisteredContract) XXX_Merge(src proto.Message) { + xxx_messageInfo_RegisteredContract.Merge(m, src) } -func (m *RegisterdContract) XXX_Size() int { +func (m *RegisteredContract) XXX_Size() int { return m.Size() } -func (m *RegisterdContract) XXX_DiscardUnknown() { - xxx_messageInfo_RegisterdContract.DiscardUnknown(m) +func (m *RegisteredContract) XXX_DiscardUnknown() { + xxx_messageInfo_RegisteredContract.DiscardUnknown(m) } -var xxx_messageInfo_RegisterdContract proto.InternalMessageInfo +var xxx_messageInfo_RegisteredContract proto.InternalMessageInfo -func (m *RegisterdContract) GetIdentity() string { +func (m *RegisteredContract) GetIdentity() string { if m != nil { return m.Identity } return "" } -func (m *RegisterdContract) GetContracts() []*ContractDetails { +func (m *RegisteredContract) GetContracts() []*ContractDetails { if m != nil { return m.Contracts } @@ -312,7 +312,7 @@ func init() { proto.RegisterType((*RequestId)(nil), "fairyring.pep.RequestId") proto.RegisterType((*PrivateRequest)(nil), "fairyring.pep.PrivateRequest") proto.RegisterType((*ContractDetails)(nil), "fairyring.pep.ContractDetails") - proto.RegisterType((*RegisterdContract)(nil), "fairyring.pep.RegisterdContract") + proto.RegisterType((*RegisteredContract)(nil), "fairyring.pep.RegisteredContract") proto.RegisterType((*ExecuteContractMsg)(nil), "fairyring.pep.ExecuteContractMsg") } @@ -320,33 +320,33 @@ func init() { proto.RegisterFile("fairyring/pep/request_id.proto", fileDescripto var fileDescriptor_3e457d2e8ff0411e = []byte{ // 422 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xc1, 0x6e, 0xd3, 0x40, - 0x10, 0x8d, 0x5b, 0x35, 0x90, 0x81, 0x52, 0x58, 0x0a, 0xb2, 0x22, 0x64, 0x55, 0xce, 0xa5, 0x70, - 0xb0, 0x25, 0x38, 0xc2, 0x05, 0x68, 0x91, 0x2a, 0x84, 0x84, 0x2c, 0x4e, 0xbd, 0x58, 0x1b, 0xef, - 0xe0, 0xae, 0xd2, 0x78, 0x37, 0xb3, 0x1b, 0x54, 0xff, 0x05, 0x7f, 0xc2, 0x6f, 0x70, 0xec, 0x91, - 0x23, 0x4a, 0x7e, 0xa4, 0xf2, 0xda, 0x1b, 0x2b, 0x3d, 0xe4, 0xb6, 0xf3, 0xf6, 0xcd, 0xdb, 0xd9, - 0x37, 0x0f, 0xa2, 0x9f, 0x5c, 0x52, 0x4d, 0xb2, 0x2a, 0x53, 0x8d, 0x3a, 0x25, 0x5c, 0x2c, 0xd1, - 0xd8, 0x5c, 0x8a, 0x44, 0x93, 0xb2, 0x8a, 0x1d, 0x6e, 0xee, 0x13, 0x8d, 0x7a, 0x7c, 0x5c, 0xaa, - 0x52, 0xb9, 0x9b, 0xb4, 0x39, 0xb5, 0xa4, 0xf1, 0xa4, 0x17, 0x29, 0xd4, 0x7c, 0xae, 0xaa, 0xd4, - 0x5c, 0x71, 0x42, 0x91, 0xdb, 0x5a, 0xa3, 0x69, 0x49, 0xf1, 0x7b, 0x18, 0x65, 0xad, 0xfa, 0x85, - 0x60, 0x21, 0x3c, 0x28, 0x08, 0xb9, 0x55, 0x14, 0x06, 0x27, 0xc1, 0xe9, 0x28, 0xf3, 0x25, 0x3b, - 0x86, 0x03, 0xc2, 0xc5, 0x85, 0x08, 0xf7, 0x1c, 0xde, 0x16, 0xf1, 0x9f, 0x00, 0x9e, 0x7c, 0x27, - 0xf9, 0x8b, 0x5b, 0xec, 0x44, 0x76, 0x48, 0xbc, 0x80, 0x21, 0xe1, 0x22, 0x97, 0xdb, 0x1a, 0xec, - 0x25, 0x0c, 0xf5, 0x72, 0x3a, 0xc3, 0x3a, 0xdc, 0x77, 0x70, 0x57, 0xb1, 0x1f, 0xf0, 0x1c, 0xab, - 0x82, 0x6a, 0x6d, 0x51, 0xe4, 0x33, 0xac, 0xdd, 0xec, 0x26, 0x3c, 0x38, 0xd9, 0x3f, 0x7d, 0xf4, - 0x76, 0x92, 0xf4, 0x06, 0xb4, 0x7f, 0x4b, 0xce, 0x3d, 0xf9, 0x6b, 0xc7, 0xcd, 0x18, 0xde, 0x87, - 0x4c, 0x7c, 0x09, 0x47, 0x9f, 0x55, 0x65, 0x89, 0x17, 0xf6, 0x0c, 0x2d, 0x97, 0xd7, 0x86, 0xbd, - 0x82, 0x11, 0x61, 0x29, 0x8d, 0x25, 0xee, 0x67, 0xee, 0x01, 0xf6, 0x1a, 0x9e, 0x16, 0x5d, 0x43, - 0xce, 0x85, 0x20, 0x34, 0xa6, 0x9b, 0xff, 0xc8, 0xe3, 0x1f, 0x5b, 0x38, 0x9e, 0xc3, 0xb3, 0xcc, - 0xf5, 0x21, 0x09, 0xff, 0x08, 0x1b, 0xc3, 0x43, 0x29, 0xb0, 0xb2, 0xd2, 0xd6, 0x9d, 0xf8, 0xa6, - 0x66, 0x1f, 0x60, 0xe4, 0x35, 0x1a, 0xd1, 0xe6, 0x63, 0x51, 0xb2, 0xb5, 0xd9, 0xe4, 0xde, 0xb0, - 0x59, 0xdf, 0x10, 0xcf, 0x81, 0x9d, 0xdf, 0x60, 0xb1, 0xb4, 0xe8, 0x49, 0xdf, 0x4c, 0xb9, 0xf3, - 0xbd, 0xde, 0xea, 0xbd, 0x2d, 0xab, 0x27, 0x70, 0xc8, 0xcb, 0x92, 0x36, 0x2e, 0x77, 0x9b, 0x78, - 0xdc, 0x80, 0xde, 0xba, 0x4f, 0x67, 0x7f, 0x57, 0x51, 0x70, 0xbb, 0x8a, 0x82, 0xff, 0xab, 0x28, - 0xf8, 0xbd, 0x8e, 0x06, 0xb7, 0xeb, 0x68, 0xf0, 0x6f, 0x1d, 0x0d, 0x2e, 0xdf, 0x94, 0xd2, 0x5e, - 0x2d, 0xa7, 0xcd, 0x22, 0xd2, 0x2f, 0x5c, 0xd2, 0xf4, 0x5a, 0x15, 0xb3, 0xb4, 0x0f, 0xdf, 0x8d, - 0xcb, 0xb0, 0x0b, 0xdd, 0x74, 0xe8, 0x52, 0xf7, 0xee, 0x2e, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x6f, - 0x5f, 0xf7, 0xe1, 0x02, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xc1, 0x6e, 0xd4, 0x30, + 0x10, 0xdd, 0xb4, 0xea, 0xc2, 0x0e, 0x94, 0x22, 0x53, 0x50, 0xb4, 0x42, 0x51, 0x95, 0xbd, 0x14, + 0x0e, 0x89, 0x04, 0x47, 0xb8, 0x00, 0x2d, 0x52, 0x85, 0x90, 0x50, 0xc4, 0xa9, 0x97, 0xc8, 0x1b, + 0x0f, 0xa9, 0xb5, 0xdd, 0xd8, 0x3b, 0x76, 0x50, 0xf3, 0x17, 0xfc, 0x09, 0xbf, 0xc1, 0xb1, 0x47, + 0x8e, 0x68, 0xf7, 0x47, 0x50, 0x9c, 0x78, 0xa3, 0xed, 0xa1, 0x37, 0xcf, 0xf3, 0x9b, 0xe7, 0xf1, + 0x9b, 0x07, 0xd1, 0x0f, 0x2e, 0xa9, 0x21, 0x59, 0x95, 0xa9, 0x46, 0x9d, 0x12, 0xae, 0x6a, 0x34, + 0x36, 0x97, 0x22, 0xd1, 0xa4, 0xac, 0x62, 0x87, 0xdb, 0xfb, 0x44, 0xa3, 0x9e, 0x1e, 0x97, 0xaa, + 0x54, 0xee, 0x26, 0x6d, 0x4f, 0x1d, 0x69, 0x3a, 0x1b, 0x44, 0x0a, 0xb5, 0x5c, 0xaa, 0x2a, 0x35, + 0x57, 0x9c, 0x50, 0xe4, 0xb6, 0xd1, 0x68, 0x3a, 0x52, 0xfc, 0x0e, 0x26, 0x59, 0xa7, 0x7e, 0x21, + 0x58, 0x08, 0x0f, 0x0a, 0x42, 0x6e, 0x15, 0x85, 0xc1, 0x49, 0x70, 0x3a, 0xc9, 0x7c, 0xc9, 0x8e, + 0xe1, 0x80, 0x70, 0x75, 0x21, 0xc2, 0x3d, 0x87, 0x77, 0x45, 0xfc, 0x3b, 0x80, 0x27, 0xdf, 0x48, + 0xfe, 0xe4, 0x16, 0x7b, 0x91, 0x7b, 0x24, 0x9e, 0xc3, 0x98, 0x70, 0x95, 0xcb, 0x5d, 0x0d, 0xf6, + 0x02, 0xc6, 0xba, 0x9e, 0x2f, 0xb0, 0x09, 0xf7, 0x1d, 0xdc, 0x57, 0xec, 0x3b, 0x3c, 0xc3, 0xaa, + 0xa0, 0x46, 0x5b, 0x14, 0xf9, 0x02, 0x1b, 0x37, 0xbb, 0x09, 0x0f, 0x4e, 0xf6, 0x4f, 0x1f, 0xbd, + 0x99, 0x25, 0x83, 0x01, 0xdd, 0xdf, 0x92, 0x73, 0x4f, 0xfe, 0xd2, 0x73, 0x33, 0x86, 0x77, 0x21, + 0x13, 0x5f, 0xc2, 0xd1, 0x27, 0x55, 0x59, 0xe2, 0x85, 0x3d, 0x43, 0xcb, 0xe5, 0xb5, 0x61, 0x2f, + 0x61, 0x42, 0x58, 0x4a, 0x63, 0x89, 0xfb, 0x99, 0x07, 0x80, 0xbd, 0x82, 0xa7, 0x45, 0xdf, 0x90, + 0x73, 0x21, 0x08, 0x8d, 0xe9, 0xe7, 0x3f, 0xf2, 0xf8, 0x87, 0x0e, 0x8e, 0x2b, 0x60, 0x99, 0xeb, + 0x43, 0x42, 0xe1, 0x5f, 0x61, 0x53, 0x78, 0x28, 0x05, 0x56, 0x56, 0xda, 0xa6, 0x57, 0xdf, 0xd6, + 0xec, 0x3d, 0x4c, 0xbc, 0x48, 0xab, 0xda, 0xfe, 0x2c, 0x4a, 0x76, 0x56, 0x9b, 0xdc, 0x99, 0x36, + 0x1b, 0x1a, 0xe2, 0x25, 0xb0, 0xf3, 0x1b, 0x2c, 0x6a, 0x8b, 0x9e, 0xf4, 0xd5, 0x94, 0xf7, 0xbe, + 0x37, 0x78, 0xbd, 0xb7, 0xe3, 0xf5, 0x0c, 0x0e, 0x79, 0x59, 0xd2, 0xd6, 0xe6, 0x7e, 0x15, 0x8f, + 0x5b, 0xd0, 0x7b, 0xf7, 0xf1, 0xec, 0xcf, 0x3a, 0x0a, 0x6e, 0xd7, 0x51, 0xf0, 0x6f, 0x1d, 0x05, + 0xbf, 0x36, 0xd1, 0xe8, 0x76, 0x13, 0x8d, 0xfe, 0x6e, 0xa2, 0xd1, 0xe5, 0xeb, 0x52, 0xda, 0xab, + 0x7a, 0xde, 0x6e, 0x22, 0xfd, 0xcc, 0x25, 0xcd, 0xaf, 0x55, 0xb1, 0x48, 0x87, 0xf4, 0xdd, 0xb8, + 0x10, 0xbb, 0xd4, 0xcd, 0xc7, 0x2e, 0x76, 0x6f, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0xf3, 0x11, + 0xcf, 0x8f, 0xe2, 0x02, 0x00, 0x00, } func (m *RequestId) Marshal() (dAtA []byte, err error) { @@ -481,7 +481,7 @@ func (m *ContractDetails) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RegisterdContract) Marshal() (dAtA []byte, err error) { +func (m *RegisteredContract) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -491,12 +491,12 @@ func (m *RegisterdContract) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RegisterdContract) MarshalTo(dAtA []byte) (int, error) { +func (m *RegisteredContract) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RegisterdContract) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *RegisteredContract) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -641,7 +641,7 @@ func (m *ContractDetails) Size() (n int) { return n } -func (m *RegisterdContract) Size() (n int) { +func (m *RegisteredContract) Size() (n int) { if m == nil { return 0 } @@ -1095,7 +1095,7 @@ func (m *ContractDetails) Unmarshal(dAtA []byte) error { } return nil } -func (m *RegisterdContract) Unmarshal(dAtA []byte) error { +func (m *RegisteredContract) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1118,10 +1118,10 @@ func (m *RegisterdContract) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RegisterdContract: wiretype end group for non-group") + return fmt.Errorf("proto: RegisteredContract: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RegisterdContract: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: RegisteredContract: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: From a4b63de03d4c61e2110f5dbd91d707cd1306ea8b Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Wed, 2 Oct 2024 21:52:50 -0400 Subject: [PATCH 24/41] Add KVStore unit tests --- x/pep/keeper/aggregated_key_share_test.go | 68 ++++++++ .../{encypted_tx.go => encrypted_tx.go} | 17 -- x/pep/keeper/encrypted_tx_test.go | 149 +++++++++++++++++ x/pep/keeper/gen_enc_tx_test.go | 79 +++++++++ x/pep/keeper/latest_height_test.go | 48 ++++++ x/pep/keeper/pep_nonce_test.go | 75 +++++++++ x/pep/keeper/pub_key_test.go | 68 ++++++++ x/pep/keeper/query_encrypted_tx_test.go | 151 ++++++++++++++++++ x/pep/keeper/request_id_test.go | 58 +++++-- 9 files changed, 680 insertions(+), 33 deletions(-) create mode 100644 x/pep/keeper/aggregated_key_share_test.go rename x/pep/keeper/{encypted_tx.go => encrypted_tx.go} (91%) create mode 100644 x/pep/keeper/encrypted_tx_test.go create mode 100644 x/pep/keeper/gen_enc_tx_test.go create mode 100644 x/pep/keeper/latest_height_test.go create mode 100644 x/pep/keeper/pep_nonce_test.go create mode 100644 x/pep/keeper/pub_key_test.go create mode 100644 x/pep/keeper/query_encrypted_tx_test.go diff --git a/x/pep/keeper/aggregated_key_share_test.go b/x/pep/keeper/aggregated_key_share_test.go new file mode 100644 index 00000000..3d157d44 --- /dev/null +++ b/x/pep/keeper/aggregated_key_share_test.go @@ -0,0 +1,68 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func createNAggregatedKeyShare(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.AggregatedKeyShare { + items := make([]types.AggregatedKeyShare, n) + for i := range items { + items[i].Height = uint64(i) + items[i].Data = random.RandHex(32) + items[i].Creator = sample.AccAddress() + + keeper.SetAggregatedKeyShare(ctx, items[i]) + } + return items +} + +func TestAggregatedKeyShareGet(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNAggregatedKeyShare(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetAggregatedKeyShare(ctx, + item.Height, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} +func TestAggregatedKeyShareRemove(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNAggregatedKeyShare(&keeper, ctx, 10) + for _, item := range items { + keeper.RemoveAggregatedKeyShare(ctx, + item.Height, + ) + _, found := keeper.GetAggregatedKeyShare(ctx, + item.Height, + ) + require.False(t, found) + } +} + +func TestAggregatedKeyShareGetAll(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNAggregatedKeyShare(&keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllAggregatedKeyShare(ctx)), + ) +} diff --git a/x/pep/keeper/encypted_tx.go b/x/pep/keeper/encrypted_tx.go similarity index 91% rename from x/pep/keeper/encypted_tx.go rename to x/pep/keeper/encrypted_tx.go index 23ef8491..12037f5a 100644 --- a/x/pep/keeper/encypted_tx.go +++ b/x/pep/keeper/encrypted_tx.go @@ -146,23 +146,6 @@ func (k Keeper) GetAllEncryptedArray(ctx context.Context) (arr []types.Encrypted return } -// RemoveEncryptedTx removes a encryptedTx from the store -func (k Keeper) RemoveEncryptedTx( - ctx context.Context, - targetHeight uint64, - index uint64, -) { - arr := k.GetEncryptedTxAllFromHeight(ctx, targetHeight) - - if index >= uint64(len(arr.EncryptedTx)) { - return - } - - arr.EncryptedTx = append(arr.EncryptedTx[:index], arr.EncryptedTx[index+1:]...) - - k.SetEncryptedTx(ctx, targetHeight, arr) -} - // RemoveAllEncryptedTxFromHeight removes all encryptedTx from the store for a particular height func (k Keeper) RemoveAllEncryptedTxFromHeight( ctx context.Context, diff --git a/x/pep/keeper/encrypted_tx_test.go b/x/pep/keeper/encrypted_tx_test.go new file mode 100644 index 00000000..afe901bb --- /dev/null +++ b/x/pep/keeper/encrypted_tx_test.go @@ -0,0 +1,149 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + "math/rand" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func createNEncryptedTx(keeper *keeper.Keeper, ctx sdk.Context, n int) (items []types.EncryptedTxArray) { + items = make([]types.EncryptedTxArray, n) + for i := range items { // i is block height + items[i].EncryptedTx = make([]types.EncryptedTx, n) + for j := 0; j < n; j++ { // j is encrypted tx index + items[i].EncryptedTx[j].Creator = sample.AccAddress() + items[i].EncryptedTx[j].Data = random.RandHex(32) + items[i].EncryptedTx[j].TargetHeight = uint64(i) + items[i].EncryptedTx[j].Index = uint64(j) + } + keeper.SetEncryptedTx(ctx, uint64(i), items[i]) + } + + return items +} + +func TestEncryptedTxAppend(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + appendTx1 := types.EncryptedTx{ + TargetHeight: rand.Uint64(), + Data: random.RandHex(32), + Creator: sample.AccAddress(), + } + tx1Index := keeper.AppendEncryptedTx(ctx, appendTx1) + _, found := keeper.GetEncryptedTx(ctx, + appendTx1.TargetHeight, + tx1Index, + ) + require.True(t, found) + appendTx2 := types.EncryptedTx{ + TargetHeight: appendTx1.TargetHeight, + Data: random.RandHex(32), + Creator: sample.AccAddress(), + } + tx2Index := keeper.AppendEncryptedTx(ctx, appendTx2) + _, found = keeper.GetEncryptedTx(ctx, + appendTx2.TargetHeight, + tx2Index, + ) + require.True(t, found) + + arr := keeper.GetEncryptedTxAllFromHeight(ctx, appendTx1.TargetHeight) + require.Equal(t, + nullify.Fill(2), + nullify.Fill(len(arr.EncryptedTx))) +} + +func TestEncryptedTxGet(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNEncryptedTx(&keeper, ctx, 10) + for _, encryptedTxs := range items { + for _, item := range encryptedTxs.EncryptedTx { + rst, found := keeper.GetEncryptedTx(ctx, + item.TargetHeight, + item.Index, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } + } +} + +func TestEncryptedTxRemoveAllFromHeight(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNEncryptedTx(&keeper, ctx, 10) + for i := range items { + keeper.RemoveAllEncryptedTxFromHeight(ctx, + uint64(i), + ) + arr := keeper.GetEncryptedTxAllFromHeight(ctx, + uint64(i), + ) + require.Equal(t, + nullify.Fill(0), + nullify.Fill(len(arr.EncryptedTx))) + } +} +func TestEncryptedTxSetProcessedHeight(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNEncryptedTx(&keeper, ctx, 10) + for i, encryptedTxs := range items { + for _, item := range encryptedTxs.EncryptedTx { + keeper.SetEncryptedTxProcessedHeight(ctx, + item.TargetHeight, + item.Index, + uint64(i*10), + ) + rst, found := keeper.GetEncryptedTx(ctx, + item.TargetHeight, + item.Index, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(rst.ProcessedAtChainHeight), + nullify.Fill(uint64(i*10)), + ) + } + } +} +func TestEncryptedTxSetAllExpired(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNEncryptedTx(&keeper, ctx, 10) + for _, encryptedTxs := range items { + for _, item := range encryptedTxs.EncryptedTx { + keeper.SetAllEncryptedTxExpired(ctx, + item.TargetHeight, + ) + rst, found := keeper.GetEncryptedTx(ctx, + item.TargetHeight, + item.Index, + ) + require.True(t, found) + require.True(t, rst.Expired) + } + } +} + +func TestEncryptedTxGetAll(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNEncryptedTx(&keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllEncryptedArray(ctx)), + ) +} diff --git a/x/pep/keeper/gen_enc_tx_test.go b/x/pep/keeper/gen_enc_tx_test.go new file mode 100644 index 00000000..7b7bed45 --- /dev/null +++ b/x/pep/keeper/gen_enc_tx_test.go @@ -0,0 +1,79 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func createNGeneralEncryptedTxEntry(keeper *keeper.Keeper, ctx sdk.Context, n int) (queue []types.GenEncTxExecutionQueue) { + items := make([]types.GeneralEncryptedTxArray, n) + queue = make([]types.GenEncTxExecutionQueue, n) + for i := range items { // i is block height + + items[i].EncryptedTx = make([]types.GeneralEncryptedTx, n) + identity := random.RandHex(32) + for j := 0; j < n; j++ { // j is encrypted tx index + items[i].EncryptedTx[j].Creator = sample.AccAddress() + items[i].EncryptedTx[j].Data = random.RandHex(32) + items[i].EncryptedTx[j].Identity = identity + items[i].EncryptedTx[j].Index = uint64(j) + } + queue[i] = types.GenEncTxExecutionQueue{ + Creator: sample.AccAddress(), + RequestId: identity, + Identity: identity, + Pubkey: random.RandHex(32), + TxList: &items[i], + AggrKeyshare: random.RandHex(32), + } + keeper.SetEntry(ctx, queue[i]) + } + + return queue +} + +func TestGeneralEncryptedTxAppend(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + out := createNGeneralEncryptedTxEntry(&keeper, ctx, 1) + appendTx1 := types.GeneralEncryptedTx{ + Identity: random.RandHex(32), + Data: random.RandHex(32), + Creator: sample.AccAddress(), + } + keeper.AppendTxToEntry(ctx, out[0].RequestId, appendTx1) + _, found := keeper.GetEntry(ctx, out[0].RequestId) + require.True(t, found) +} + +func TestEntryGet(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNGeneralEncryptedTxEntry(&keeper, ctx, 10) + for _, item := range items { + out, found := keeper.GetEntry(ctx, item.RequestId) + require.True(t, found) + require.Equal(t, nullify.Fill(out), nullify.Fill(item)) + } +} + +func TestEntryRemove(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNGeneralEncryptedTxEntry(&keeper, ctx, 10) + for _, item := range items { + keeper.RemoveEntry(ctx, item.RequestId) + _, found := keeper.GetEntry(ctx, item.RequestId) + require.False(t, found) + } +} diff --git a/x/pep/keeper/latest_height_test.go b/x/pep/keeper/latest_height_test.go new file mode 100644 index 00000000..0bb93314 --- /dev/null +++ b/x/pep/keeper/latest_height_test.go @@ -0,0 +1,48 @@ +package keeper_test + +import ( + "context" + "github.com/Fairblock/fairyring/testutil/random" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func createLatestHeight(keeper keeper.Keeper, ctx context.Context) string { + randHeight := random.RandHex(16) + keeper.SetLatestHeight(ctx, randHeight) + return randHeight +} + +func TestLatestHeightGet(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + latestHeight := createLatestHeight(keeper, ctx) + result := keeper.GetLatestHeight(ctx) + require.Equal(t, + nullify.Fill(latestHeight), + nullify.Fill(result), + ) +} + +func createLastExecutedHeight(keeper keeper.Keeper, ctx context.Context) string { + randHeight := random.RandHex(16) + keeper.SetLastExecutedHeight(ctx, randHeight) + return randHeight +} + +func TestLastExecutedHeightGet(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + latestHeight := createLastExecutedHeight(keeper, ctx) + result := keeper.GetLastExecutedHeight(ctx) + require.Equal(t, + nullify.Fill(latestHeight), + nullify.Fill(result), + ) +} diff --git a/x/pep/keeper/pep_nonce_test.go b/x/pep/keeper/pep_nonce_test.go new file mode 100644 index 00000000..4ab37866 --- /dev/null +++ b/x/pep/keeper/pep_nonce_test.go @@ -0,0 +1,75 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/sample" + "math/rand" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func createNPepNonce(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.PepNonce { + items := make([]types.PepNonce, n) + for i := range items { + items[i].Address = sample.AccAddress() + items[i].Nonce = rand.Uint64() + + keeper.SetPepNonce(ctx, items[i]) + } + return items +} + +func TestPepNonceGet(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNPepNonce(&keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetPepNonce(ctx, + item.Address, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} +func TestPepNonceRemove(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNPepNonce(&keeper, ctx, 10) + for _, item := range items { + nonce, found := keeper.GetPepNonce(ctx, + item.Address, + ) + require.True(t, found) + // pep nonce default is 1 + require.NotEqual(t, nullify.Fill(1), nullify.Fill(nonce.Nonce)) + + keeper.RemovePepNonce(ctx, + item.Address, + ) + nonce, found = keeper.GetPepNonce(ctx, + item.Address, + ) + require.True(t, found) + require.Equal(t, nullify.Fill(uint64(1)), nullify.Fill(nonce.Nonce)) + } +} + +func TestPepNonceGetAll(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNPepNonce(&keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllPepNonce(ctx)), + ) +} diff --git a/x/pep/keeper/pub_key_test.go b/x/pep/keeper/pub_key_test.go new file mode 100644 index 00000000..f539684d --- /dev/null +++ b/x/pep/keeper/pub_key_test.go @@ -0,0 +1,68 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "math/rand" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + commontypes "github.com/Fairblock/fairyring/x/common/types" + "github.com/Fairblock/fairyring/x/pep/keeper" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func createActivePubKeys(keeper *keeper.Keeper, ctx sdk.Context) commontypes.ActivePublicKey { + var items commontypes.ActivePublicKey + items.PublicKey = random.RandHex(10) + items.Expiry = rand.Uint64() + keeper.SetActivePubKey(ctx, items) + return items +} + +func createQueuedPubKeys(keeper *keeper.Keeper, ctx sdk.Context) commontypes.QueuedPublicKey { + var items commontypes.QueuedPublicKey + items.PublicKey = random.RandHex(10) + items.Expiry = rand.Uint64() + keeper.SetQueuedPubKey(ctx, items) + return items +} + +func TestActivePubKeyGet(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + item := createActivePubKeys(&keeper, ctx) + rst, found := keeper.GetActivePubKey(ctx) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) +} + +func TestQueuedPubKeyGet(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + item := createQueuedPubKeys(&keeper, ctx) + rst, found := keeper.GetQueuedPubKey(ctx) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) +} + +func TestActivePubKeyRemoved(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + createActivePubKeys(&keeper, ctx) + keeper.DeleteActivePubKey(ctx) + _, found := keeper.GetActivePubKey(ctx) + require.False(t, found) +} + +func TestQueuedPubKeyRemoved(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + createQueuedPubKeys(&keeper, ctx) + keeper.DeleteQueuedPubKey(ctx) + _, found := keeper.GetQueuedPubKey(ctx) + require.False(t, found) +} diff --git a/x/pep/keeper/query_encrypted_tx_test.go b/x/pep/keeper/query_encrypted_tx_test.go new file mode 100644 index 00000000..6e41500c --- /dev/null +++ b/x/pep/keeper/query_encrypted_tx_test.go @@ -0,0 +1,151 @@ +package keeper_test + +import ( + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestEncryptedTxQuerySingle(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNEncryptedTx(&keeper, ctx, 10) + + for _, tc := range []struct { + desc string + request *types.QueryGetEncryptedTxRequest + response *types.QueryGetEncryptedTxResponse + err error + }{ + { + desc: "First", + request: &types.QueryGetEncryptedTxRequest{ + TargetHeight: msgs[0].EncryptedTx[0].TargetHeight, + Index: msgs[0].EncryptedTx[0].Index, + }, + response: &types.QueryGetEncryptedTxResponse{EncryptedTx: msgs[0].EncryptedTx[0]}, + }, + { + desc: "Second", + request: &types.QueryGetEncryptedTxRequest{ + TargetHeight: msgs[1].EncryptedTx[0].TargetHeight, + Index: msgs[1].EncryptedTx[0].Index, + }, + response: &types.QueryGetEncryptedTxResponse{EncryptedTx: msgs[1].EncryptedTx[0]}, + }, + { + desc: "KeyNotFound", + request: &types.QueryGetEncryptedTxRequest{ + TargetHeight: 100000, + Index: 100000, + }, + err: status.Error(codes.NotFound, "not found"), + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.EncryptedTx(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestEncryptedTxQueryAll(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNEncryptedTx(&keeper, ctx, 5) + + resp, err := keeper.EncryptedTxAll(wctx, &types.QueryAllEncryptedTxRequest{ + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 0, + CountTotal: false, + }, + }) + require.NoError(t, err) + require.Equal(t, len(resp.EncryptedTxArray), len(msgs)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.EncryptedTxArray), + ) +} + +func TestEncryptedTxQueryPaginated(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNEncryptedTx(&keeper, ctx, 5) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllEncryptedTxRequest { + return &types.QueryAllEncryptedTxRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.EncryptedTxAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.EncryptedTxArray), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.EncryptedTxArray), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.EncryptedTxAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.EncryptedTxArray), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.EncryptedTxArray), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.EncryptedTxAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.EncryptedTxArray), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.EncryptedTxAll(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) + }) +} diff --git a/x/pep/keeper/request_id_test.go b/x/pep/keeper/request_id_test.go index 5adf6196..6fedd195 100644 --- a/x/pep/keeper/request_id_test.go +++ b/x/pep/keeper/request_id_test.go @@ -2,6 +2,9 @@ package keeper_test import ( "context" + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + commontypes "github.com/Fairblock/fairyring/x/common/types" "strconv" "testing" @@ -18,7 +21,8 @@ var _ = strconv.IntSize func createNRequestId(keeper keeper.Keeper, ctx context.Context, n int) []types.RequestId { items := make([]types.RequestId, n) for i := range items { - items[i].Creator = strconv.Itoa(i) + items[i].Creator = sample.AccAddress() + items[i].ReqId = random.RandHex(16) keeper.SetRequestId(ctx, items[i]) } @@ -31,7 +35,7 @@ func TestRequestIdGet(t *testing.T) { for _, item := range items { rst, found := keeper.GetRequestId(ctx, item.Creator, - "", + item.ReqId, ) require.True(t, found) require.Equal(t, @@ -41,20 +45,6 @@ func TestRequestIdGet(t *testing.T) { } } -// func TestRequestIdRemove(t *testing.T) { -// keeper, ctx := keepertest.PepKeeper(t) -// items := createNRequestId(keeper, ctx, 10) -// for _, item := range items { -// keeper.RemoveRequestId(ctx, -// item.Creator, -// ) -// _, found := keeper.GetRequestId(ctx, -// item.Creator, -// ) -// require.False(t, found) -// } -// } - func TestRequestIdGetAll(t *testing.T) { keeper, ctx := keepertest.PepKeeper(t) items := createNRequestId(keeper, ctx, 10) @@ -63,3 +53,39 @@ func TestRequestIdGetAll(t *testing.T) { nullify.Fill(keeper.GetAllRequestId(ctx)), ) } + +func createNPrivateRequestId(keeper keeper.Keeper, ctx context.Context, n int) []types.PrivateRequest { + items := make([]types.PrivateRequest, n) + for i := range items { + items[i].Creator = sample.AccAddress() + items[i].ReqId = random.RandHex(16) + items[i].EncryptedKeyshares = make([]*commontypes.EncryptedKeyshare, 0) + + keeper.SetPrivateRequest(ctx, items[i]) + } + return items +} + +func TestPrivateRequestIdGet(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNPrivateRequestId(keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetPrivateRequest(ctx, + item.ReqId, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} + +func TestPrivateRequestIdGetAll(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + items := createNPrivateRequestId(keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllPrivateRequest(ctx)), + ) +} From 7ae1d8889a8927ad7fefa7b63e339bd8f805b569 Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Wed, 2 Oct 2024 21:53:22 -0400 Subject: [PATCH 25/41] Add query pep nonce & pub key tests --- x/pep/keeper/query_pep_nonce_test.go | 130 +++++++++++++++++++++++++++ x/pep/keeper/query_pub_key_test.go | 51 +++++++++++ 2 files changed, 181 insertions(+) create mode 100644 x/pep/keeper/query_pep_nonce_test.go create mode 100644 x/pep/keeper/query_pub_key_test.go diff --git a/x/pep/keeper/query_pep_nonce_test.go b/x/pep/keeper/query_pep_nonce_test.go new file mode 100644 index 00000000..2b04b527 --- /dev/null +++ b/x/pep/keeper/query_pep_nonce_test.go @@ -0,0 +1,130 @@ +package keeper_test + +import ( + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestPepNonceQuerySingle(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNPepNonce(&keeper, ctx, 2) + for _, tc := range []struct { + desc string + request *types.QueryGetPepNonceRequest + response *types.QueryGetPepNonceResponse + err error + }{ + { + desc: "First", + request: &types.QueryGetPepNonceRequest{ + Address: msgs[0].Address, + }, + response: &types.QueryGetPepNonceResponse{PepNonce: msgs[0]}, + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.PepNonce(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestPepNonceQueryAll(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNPepNonce(&keeper, ctx, 5) + + all, err := keeper.PepNonceAll(wctx, &types.QueryAllPepNonceRequest{ + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 0, + CountTotal: false, + }}, + ) + require.NoError(t, err) + require.Equal(t, nullify.Fill(len(all.PepNonce)), nullify.Fill(len(msgs))) + require.ElementsMatch(t, nullify.Fill(all.PepNonce), nullify.Fill(msgs)) +} + +func TestPepNonceQueryPaginated(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNPepNonce(&keeper, ctx, 5) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllPepNonceRequest { + return &types.QueryAllPepNonceRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.PepNonceAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.PepNonce), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.PepNonce), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.PepNonceAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.PepNonce), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.PepNonce), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.PepNonceAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.PepNonce), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.PepNonceAll(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) + }) +} diff --git a/x/pep/keeper/query_pub_key_test.go b/x/pep/keeper/query_pub_key_test.go new file mode 100644 index 00000000..7b8b8867 --- /dev/null +++ b/x/pep/keeper/query_pub_key_test.go @@ -0,0 +1,51 @@ +package keeper_test + +import ( + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "testing" +) + +func TestPubKeyQuery(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + activePubKey := createActivePubKeys(&keeper, wctx) + queuedPubKey := createQueuedPubKeys(&keeper, wctx) + for _, tc := range []struct { + desc string + request *types.QueryPubKeyRequest + response *types.QueryPubKeyResponse + err error + }{ + { + desc: "QueryPubKey", + request: &types.QueryPubKeyRequest{}, + response: &types.QueryPubKeyResponse{ + ActivePubKey: activePubKey, + QueuedPubKey: queuedPubKey, + }, + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.PubKey(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} From 5be76142c2cc7d1781b1a445d3ebbfffb8683e5d Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Thu, 3 Oct 2024 15:33:21 +0530 Subject: [PATCH 26/41] add check on registrar address --- app/pep.go | 1 + testutil/keeper/pep.go | 1 + x/pep/keeper/contract.go | 2 +- x/pep/keeper/keeper.go | 21 ++++++++++++++------- x/pep/keeper/msg_register_contract.go | 14 ++++++++++++++ x/pep/types/expected_keepers.go | 7 +++++++ 6 files changed, 38 insertions(+), 8 deletions(-) diff --git a/app/pep.go b/app/pep.go index a0878403..f1ea1aee 100644 --- a/app/pep.go +++ b/app/pep.go @@ -37,6 +37,7 @@ func (app *App) registerPepModule() (porttypes.IBCModule, error) { app.AccountKeeper, app.BankKeeper, contractKeeper, + app.WasmKeeper, ) // register IBC modules diff --git a/testutil/keeper/pep.go b/testutil/keeper/pep.go index caa6a606..79280efd 100644 --- a/testutil/keeper/pep.go +++ b/testutil/keeper/pep.go @@ -61,6 +61,7 @@ func PepKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { nil, nil, nil, + nil, ) ctx := sdk.NewContext(stateStore, cmtproto.Header{}, false, log.NewNopLogger()) diff --git a/x/pep/keeper/contract.go b/x/pep/keeper/contract.go index 8d5a736c..bf4e0f9f 100644 --- a/x/pep/keeper/contract.go +++ b/x/pep/keeper/contract.go @@ -98,7 +98,7 @@ func (k Keeper) ExecuteContract(ctx sdk.Context, contractAddr string, msg types. } wasmAddr := authtypes.NewModuleAddress(wasmtypes.ModuleName) - _, err = k.wasmKeeper.Execute(ctx, addr, wasmAddr, msgBytes, sdk.Coins{}) + _, err = k.contractKeeper.Execute(ctx, addr, wasmAddr, msgBytes, sdk.Coins{}) if err != nil { k.logger.Error("error executing contract: %s; error: %v", contractAddr, err) } diff --git a/x/pep/keeper/keeper.go b/x/pep/keeper/keeper.go index 701aa87c..0b94440a 100644 --- a/x/pep/keeper/keeper.go +++ b/x/pep/keeper/keeper.go @@ -34,9 +34,10 @@ type ( // capabilityScopedFn func(string) capabilitykeeper.ScopedKeeper scopedKeeper exported.ScopedKeeper - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper - wasmKeeper types.WasmKeeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + contractKeeper types.ContractKeeper + wasmKeeper types.WasmKeeper } ) @@ -51,6 +52,7 @@ func NewKeeper( accountKeeper types.AccountKeeper, bankKeeper types.BankKeeper, + contractKeeper types.ContractKeeper, wasmKeeper types.WasmKeeper, ) Keeper { if _, err := sdk.AccAddressFromBech32(authority); err != nil { @@ -64,10 +66,11 @@ func NewKeeper( logger: logger, ibcKeeperFn: ibcKeeperFn, // capabilityScopedFn: capabilityScopedFn, - scopedKeeper: scopedKeeper, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - wasmKeeper: wasmKeeper, + scopedKeeper: scopedKeeper, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + contractKeeper: contractKeeper, + wasmKeeper: wasmKeeper, } } @@ -163,3 +166,7 @@ func (k Keeper) SetRequestCount(ctx sdk.Context, requestNumber uint64) { func (k Keeper) SetWasmKeeper(wk types.WasmKeeper) { k.wasmKeeper = wk } + +func (k Keeper) SetContractKeeper(ck types.ContractKeeper) { + k.contractKeeper = ck +} diff --git a/x/pep/keeper/msg_register_contract.go b/x/pep/keeper/msg_register_contract.go index 36ffcd70..0b0ae2a6 100644 --- a/x/pep/keeper/msg_register_contract.go +++ b/x/pep/keeper/msg_register_contract.go @@ -14,6 +14,20 @@ func (k msgServer) RegisterContract( ) (*types.MsgRegisterContractResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + contracAddr, err := sdk.AccAddressFromBech32(msg.ContractAddress) + if err != nil { + return nil, errors.New("invalid contract address") + } + + contractInfo := k.wasmKeeper.GetContractInfo(ctx, contracAddr) + if contractInfo == nil { + return nil, errors.New("contract information not found") + } + + if msg.Creator != contractInfo.Admin && msg.Creator != contractInfo.Creator { + return nil, errors.New("unautorized registration; only cretor and admin can register") + } + var contDetails = types.ContractDetails{ Registrar: msg.Creator, ContractAddress: msg.ContractAddress, diff --git a/x/pep/types/expected_keepers.go b/x/pep/types/expected_keepers.go index 9de8b4da..820d35b4 100644 --- a/x/pep/types/expected_keepers.go +++ b/x/pep/types/expected_keepers.go @@ -3,6 +3,7 @@ package types import ( "context" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -30,5 +31,11 @@ type ParamSubspace interface { // WasmKeeper defines the expected interface for the wasm module. type WasmKeeper interface { + GetContractInfo(ctx context.Context, contractAddress sdk.AccAddress) *wasmtypes.ContractInfo + HasContractInfo(ctx context.Context, contractAddress sdk.AccAddress) bool +} + +// ContractKeeper defines the expected interface for the wasm module. +type ContractKeeper interface { Execute(ctx sdk.Context, contractAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) ([]byte, error) } From 5b8ff152732f29af0bd6b582706ba0c5c9835e93 Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Thu, 3 Oct 2024 22:14:50 +0530 Subject: [PATCH 27/41] adding tx to deregister contract; updating test script --- api/fairyring/pep/tx.pulsar.go | 1190 ++++++++++++++++++-- api/fairyring/pep/tx_grpc.pb.go | 37 + proto/fairyring/pep/tx.proto | 12 +- scripts/tests/pep.sh | 35 + x/pep/client/cli/tx.go | 1 + x/pep/client/cli/tx_unregister_contract.go | 41 + x/pep/keeper/contract.go | 7 + x/pep/keeper/msg_unregister_contract.go | 56 + x/pep/module/module.go | 4 + x/pep/types/msg_unregister_contract.go | 33 + x/pep/types/tx.pb.go | 547 ++++++++- 11 files changed, 1821 insertions(+), 142 deletions(-) create mode 100644 x/pep/client/cli/tx_unregister_contract.go create mode 100644 x/pep/keeper/msg_unregister_contract.go create mode 100644 x/pep/types/msg_unregister_contract.go diff --git a/api/fairyring/pep/tx.pulsar.go b/api/fairyring/pep/tx.pulsar.go index 9437a91a..9035a68e 100644 --- a/api/fairyring/pep/tx.pulsar.go +++ b/api/fairyring/pep/tx.pulsar.go @@ -7732,6 +7732,910 @@ func (x *fastReflection_MsgRegisterContractResponse) ProtoMethods() *protoiface. } } +var ( + md_MsgUnregisterContract protoreflect.MessageDescriptor + fd_MsgUnregisterContract_creator protoreflect.FieldDescriptor + fd_MsgUnregisterContract_contract_address protoreflect.FieldDescriptor + fd_MsgUnregisterContract_identity protoreflect.FieldDescriptor +) + +func init() { + file_fairyring_pep_tx_proto_init() + md_MsgUnregisterContract = File_fairyring_pep_tx_proto.Messages().ByName("MsgUnregisterContract") + fd_MsgUnregisterContract_creator = md_MsgUnregisterContract.Fields().ByName("creator") + fd_MsgUnregisterContract_contract_address = md_MsgUnregisterContract.Fields().ByName("contract_address") + fd_MsgUnregisterContract_identity = md_MsgUnregisterContract.Fields().ByName("identity") +} + +var _ protoreflect.Message = (*fastReflection_MsgUnregisterContract)(nil) + +type fastReflection_MsgUnregisterContract MsgUnregisterContract + +func (x *MsgUnregisterContract) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgUnregisterContract)(x) +} + +func (x *MsgUnregisterContract) slowProtoReflect() protoreflect.Message { + mi := &file_fairyring_pep_tx_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_MsgUnregisterContract_messageType fastReflection_MsgUnregisterContract_messageType +var _ protoreflect.MessageType = fastReflection_MsgUnregisterContract_messageType{} + +type fastReflection_MsgUnregisterContract_messageType struct{} + +func (x fastReflection_MsgUnregisterContract_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgUnregisterContract)(nil) +} +func (x fastReflection_MsgUnregisterContract_messageType) New() protoreflect.Message { + return new(fastReflection_MsgUnregisterContract) +} +func (x fastReflection_MsgUnregisterContract_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgUnregisterContract +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgUnregisterContract) Descriptor() protoreflect.MessageDescriptor { + return md_MsgUnregisterContract +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_MsgUnregisterContract) Type() protoreflect.MessageType { + return _fastReflection_MsgUnregisterContract_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgUnregisterContract) New() protoreflect.Message { + return new(fastReflection_MsgUnregisterContract) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgUnregisterContract) Interface() protoreflect.ProtoMessage { + return (*MsgUnregisterContract)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_MsgUnregisterContract) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Creator != "" { + value := protoreflect.ValueOfString(x.Creator) + if !f(fd_MsgUnregisterContract_creator, value) { + return + } + } + if x.ContractAddress != "" { + value := protoreflect.ValueOfString(x.ContractAddress) + if !f(fd_MsgUnregisterContract_contract_address, value) { + return + } + } + if x.Identity != "" { + value := protoreflect.ValueOfString(x.Identity) + if !f(fd_MsgUnregisterContract_identity, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_MsgUnregisterContract) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "fairyring.pep.MsgUnregisterContract.creator": + return x.Creator != "" + case "fairyring.pep.MsgUnregisterContract.contract_address": + return x.ContractAddress != "" + case "fairyring.pep.MsgUnregisterContract.identity": + return x.Identity != "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContract does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgUnregisterContract) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "fairyring.pep.MsgUnregisterContract.creator": + x.Creator = "" + case "fairyring.pep.MsgUnregisterContract.contract_address": + x.ContractAddress = "" + case "fairyring.pep.MsgUnregisterContract.identity": + x.Identity = "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContract does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_MsgUnregisterContract) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "fairyring.pep.MsgUnregisterContract.creator": + value := x.Creator + return protoreflect.ValueOfString(value) + case "fairyring.pep.MsgUnregisterContract.contract_address": + value := x.ContractAddress + return protoreflect.ValueOfString(value) + case "fairyring.pep.MsgUnregisterContract.identity": + value := x.Identity + return protoreflect.ValueOfString(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContract does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgUnregisterContract) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "fairyring.pep.MsgUnregisterContract.creator": + x.Creator = value.Interface().(string) + case "fairyring.pep.MsgUnregisterContract.contract_address": + x.ContractAddress = value.Interface().(string) + case "fairyring.pep.MsgUnregisterContract.identity": + x.Identity = value.Interface().(string) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContract does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgUnregisterContract) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.MsgUnregisterContract.creator": + panic(fmt.Errorf("field creator of message fairyring.pep.MsgUnregisterContract is not mutable")) + case "fairyring.pep.MsgUnregisterContract.contract_address": + panic(fmt.Errorf("field contract_address of message fairyring.pep.MsgUnregisterContract is not mutable")) + case "fairyring.pep.MsgUnregisterContract.identity": + panic(fmt.Errorf("field identity of message fairyring.pep.MsgUnregisterContract is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContract does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_MsgUnregisterContract) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "fairyring.pep.MsgUnregisterContract.creator": + return protoreflect.ValueOfString("") + case "fairyring.pep.MsgUnregisterContract.contract_address": + return protoreflect.ValueOfString("") + case "fairyring.pep.MsgUnregisterContract.identity": + return protoreflect.ValueOfString("") + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContract")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContract does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_MsgUnregisterContract) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in fairyring.pep.MsgUnregisterContract", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_MsgUnregisterContract) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgUnregisterContract) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_MsgUnregisterContract) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_MsgUnregisterContract) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgUnregisterContract) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.Creator) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.ContractAddress) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.Identity) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*MsgUnregisterContract) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.Identity) > 0 { + i -= len(x.Identity) + copy(dAtA[i:], x.Identity) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Identity))) + i-- + dAtA[i] = 0x1a + } + if len(x.ContractAddress) > 0 { + i -= len(x.ContractAddress) + copy(dAtA[i:], x.ContractAddress) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ContractAddress))) + i-- + dAtA[i] = 0x12 + } + if len(x.Creator) > 0 { + i -= len(x.Creator) + copy(dAtA[i:], x.Creator) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Creator))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*MsgUnregisterContract) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgUnregisterContract: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgUnregisterContract: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.ContractAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Identity", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Identity = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_MsgUnregisterContractResponse protoreflect.MessageDescriptor +) + +func init() { + file_fairyring_pep_tx_proto_init() + md_MsgUnregisterContractResponse = File_fairyring_pep_tx_proto.Messages().ByName("MsgUnregisterContractResponse") +} + +var _ protoreflect.Message = (*fastReflection_MsgUnregisterContractResponse)(nil) + +type fastReflection_MsgUnregisterContractResponse MsgUnregisterContractResponse + +func (x *MsgUnregisterContractResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgUnregisterContractResponse)(x) +} + +func (x *MsgUnregisterContractResponse) slowProtoReflect() protoreflect.Message { + mi := &file_fairyring_pep_tx_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_MsgUnregisterContractResponse_messageType fastReflection_MsgUnregisterContractResponse_messageType +var _ protoreflect.MessageType = fastReflection_MsgUnregisterContractResponse_messageType{} + +type fastReflection_MsgUnregisterContractResponse_messageType struct{} + +func (x fastReflection_MsgUnregisterContractResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgUnregisterContractResponse)(nil) +} +func (x fastReflection_MsgUnregisterContractResponse_messageType) New() protoreflect.Message { + return new(fastReflection_MsgUnregisterContractResponse) +} +func (x fastReflection_MsgUnregisterContractResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgUnregisterContractResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgUnregisterContractResponse) Descriptor() protoreflect.MessageDescriptor { + return md_MsgUnregisterContractResponse +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_MsgUnregisterContractResponse) Type() protoreflect.MessageType { + return _fastReflection_MsgUnregisterContractResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgUnregisterContractResponse) New() protoreflect.Message { + return new(fastReflection_MsgUnregisterContractResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgUnregisterContractResponse) Interface() protoreflect.ProtoMessage { + return (*MsgUnregisterContractResponse)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_MsgUnregisterContractResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_MsgUnregisterContractResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgUnregisterContractResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_MsgUnregisterContractResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContractResponse does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgUnregisterContractResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgUnregisterContractResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_MsgUnregisterContractResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: fairyring.pep.MsgUnregisterContractResponse")) + } + panic(fmt.Errorf("message fairyring.pep.MsgUnregisterContractResponse does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_MsgUnregisterContractResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in fairyring.pep.MsgUnregisterContractResponse", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_MsgUnregisterContractResponse) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgUnregisterContractResponse) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_MsgUnregisterContractResponse) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_MsgUnregisterContractResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgUnregisterContractResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*MsgUnregisterContractResponse) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*MsgUnregisterContractResponse) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgUnregisterContractResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgUnregisterContractResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -8412,6 +9316,83 @@ func (*MsgRegisterContractResponse) Descriptor() ([]byte, []int) { return file_fairyring_pep_tx_proto_rawDescGZIP(), []int{16} } +type MsgUnregisterContract struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + ContractAddress string `protobuf:"bytes,2,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"` + Identity string `protobuf:"bytes,3,opt,name=identity,proto3" json:"identity,omitempty"` +} + +func (x *MsgUnregisterContract) Reset() { + *x = MsgUnregisterContract{} + if protoimpl.UnsafeEnabled { + mi := &file_fairyring_pep_tx_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgUnregisterContract) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgUnregisterContract) ProtoMessage() {} + +// Deprecated: Use MsgUnregisterContract.ProtoReflect.Descriptor instead. +func (*MsgUnregisterContract) Descriptor() ([]byte, []int) { + return file_fairyring_pep_tx_proto_rawDescGZIP(), []int{17} +} + +func (x *MsgUnregisterContract) GetCreator() string { + if x != nil { + return x.Creator + } + return "" +} + +func (x *MsgUnregisterContract) GetContractAddress() string { + if x != nil { + return x.ContractAddress + } + return "" +} + +func (x *MsgUnregisterContract) GetIdentity() string { + if x != nil { + return x.Identity + } + return "" +} + +type MsgUnregisterContractResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *MsgUnregisterContractResponse) Reset() { + *x = MsgUnregisterContractResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_fairyring_pep_tx_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgUnregisterContractResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgUnregisterContractResponse) ProtoMessage() {} + +// Deprecated: Use MsgUnregisterContractResponse.ProtoReflect.Descriptor instead. +func (*MsgUnregisterContractResponse) Descriptor() ([]byte, []int) { + return file_fairyring_pep_tx_proto_rawDescGZIP(), []int{18} +} + var File_fairyring_pep_tx_proto protoreflect.FileDescriptor var file_fairyring_pep_tx_proto_rawDesc = []byte{ @@ -8524,79 +9505,96 @@ var file_fairyring_pep_tx_proto_rawDesc = []byte{ 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, 0x0c, 0x82, 0xe7, 0xb0, 0x2a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x1d, 0x0a, 0x1b, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe3, 0x07, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, - 0x56, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, - 0x1e, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, - 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, - 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, - 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x12, 0x23, 0x2e, 0x66, - 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, - 0x78, 0x1a, 0x2b, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, - 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, - 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x45, - 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x12, 0x2a, 0x2e, 0x66, 0x61, 0x69, - 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x1a, 0x2b, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x86, 0x01, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x55, + 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x3a, 0x0c, 0x82, 0xe7, 0xb0, 0x2a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, + 0x22, 0x1f, 0x0a, 0x1d, 0x4d, 0x73, 0x67, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x32, 0xcd, 0x08, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x56, 0x0a, 0x0c, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1e, 0x2e, 0x66, 0x61, 0x69, 0x72, + 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x26, 0x2e, 0x66, 0x61, 0x69, 0x72, + 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x65, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x12, 0x23, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x12, - 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, - 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x1a, 0x32, 0x2e, 0x66, 0x61, - 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, - 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x74, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0x28, 0x2e, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, + 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, 0x1a, 0x2b, 0x2e, 0x66, 0x61, + 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, + 0x65, 0x64, 0x54, 0x78, 0x12, 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x47, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x54, 0x78, + 0x1a, 0x2b, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, + 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x65, 0x64, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, + 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x64, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x12, 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, + 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, + 0x53, 0x68, 0x61, 0x72, 0x65, 0x1a, 0x32, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, + 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, - 0x61, 0x72, 0x65, 0x1a, 0x30, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x72, 0x65, 0x12, 0x28, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0x24, 0x2e, 0x66, 0x61, + 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x1a, 0x30, 0x2e, + 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, + 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x68, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, + 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0x24, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, + 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x1a, 0x2c, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x1a, 0x2c, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, - 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x4b, - 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x74, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, - 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x28, 0x2e, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x1a, 0x30, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x69, 0x74, 0x79, 0x12, 0x28, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x66, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x30, 0x2e, + 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x6b, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, + 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, + 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x1a, 0x2d, 0x2e, + 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, + 0x67, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, + 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x10, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x12, 0x22, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, + 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x1a, 0x2a, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x68, 0x0a, 0x12, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x24, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, + 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x1a, 0x2c, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, - 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, - 0x72, 0x65, 0x73, 0x1a, 0x2d, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, - 0x65, 0x4b, 0x65, 0x79, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x62, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x22, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, - 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x1a, 0x2a, 0x2e, 0x66, 0x61, 0x69, - 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, 0x2a, 0x01, 0x42, 0x91, 0x01, - 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x65, 0x70, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x70, 0xa2, 0x02, - 0x03, 0x46, 0x50, 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, - 0x2e, 0x50, 0x65, 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, - 0x5c, 0x50, 0x65, 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, - 0x5c, 0x50, 0x65, 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x0e, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x50, 0x65, - 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, 0x2a, + 0x01, 0x42, 0x91, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, + 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x65, 0x70, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, + 0x65, 0x70, 0xa2, 0x02, 0x03, 0x46, 0x50, 0x58, 0xaa, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, + 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x70, 0xca, 0x02, 0x0d, 0x46, 0x61, 0x69, 0x72, 0x79, + 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0xe2, 0x02, 0x19, 0x46, 0x61, 0x69, 0x72, 0x79, + 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x50, 0x65, 0x70, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x46, 0x61, 0x69, 0x72, 0x79, 0x72, 0x69, 0x6e, 0x67, + 0x3a, 0x3a, 0x50, 0x65, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -8611,7 +9609,7 @@ func file_fairyring_pep_tx_proto_rawDescGZIP() []byte { return file_fairyring_pep_tx_proto_rawDescData } -var file_fairyring_pep_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_fairyring_pep_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_fairyring_pep_tx_proto_goTypes = []interface{}{ (*MsgUpdateParams)(nil), // 0: fairyring.pep.MsgUpdateParams (*MsgUpdateParamsResponse)(nil), // 1: fairyring.pep.MsgUpdateParamsResponse @@ -8630,12 +9628,14 @@ var file_fairyring_pep_tx_proto_goTypes = []interface{}{ (*MsgGetPrivateKeysharesResponse)(nil), // 14: fairyring.pep.MsgGetPrivateKeysharesResponse (*MsgRegisterContract)(nil), // 15: fairyring.pep.MsgRegisterContract (*MsgRegisterContractResponse)(nil), // 16: fairyring.pep.MsgRegisterContractResponse - (*Params)(nil), // 17: fairyring.pep.Params - (*durationpb.Duration)(nil), // 18: google.protobuf.Duration + (*MsgUnregisterContract)(nil), // 17: fairyring.pep.MsgUnregisterContract + (*MsgUnregisterContractResponse)(nil), // 18: fairyring.pep.MsgUnregisterContractResponse + (*Params)(nil), // 19: fairyring.pep.Params + (*durationpb.Duration)(nil), // 20: google.protobuf.Duration } var file_fairyring_pep_tx_proto_depIdxs = []int32{ - 17, // 0: fairyring.pep.MsgUpdateParams.params:type_name -> fairyring.pep.Params - 18, // 1: fairyring.pep.MsgRequestGeneralKeyshare.estimated_delay:type_name -> google.protobuf.Duration + 19, // 0: fairyring.pep.MsgUpdateParams.params:type_name -> fairyring.pep.Params + 20, // 1: fairyring.pep.MsgRequestGeneralKeyshare.estimated_delay:type_name -> google.protobuf.Duration 0, // 2: fairyring.pep.Msg.UpdateParams:input_type -> fairyring.pep.MsgUpdateParams 2, // 3: fairyring.pep.Msg.SubmitEncryptedTx:input_type -> fairyring.pep.MsgSubmitEncryptedTx 3, // 4: fairyring.pep.Msg.SubmitGeneralEncryptedTx:input_type -> fairyring.pep.MsgSubmitGeneralEncryptedTx @@ -8645,17 +9645,19 @@ var file_fairyring_pep_tx_proto_depIdxs = []int32{ 11, // 8: fairyring.pep.Msg.RequestPrivateIdentity:input_type -> fairyring.pep.MsgRequestPrivateIdentity 13, // 9: fairyring.pep.Msg.GetPrivateKeyshares:input_type -> fairyring.pep.MsgGetPrivateKeyshares 15, // 10: fairyring.pep.Msg.RegisterContract:input_type -> fairyring.pep.MsgRegisterContract - 1, // 11: fairyring.pep.Msg.UpdateParams:output_type -> fairyring.pep.MsgUpdateParamsResponse - 4, // 12: fairyring.pep.Msg.SubmitEncryptedTx:output_type -> fairyring.pep.MsgSubmitEncryptedTxResponse - 4, // 13: fairyring.pep.Msg.SubmitGeneralEncryptedTx:output_type -> fairyring.pep.MsgSubmitEncryptedTxResponse - 6, // 14: fairyring.pep.Msg.CreateAggregatedKeyShare:output_type -> fairyring.pep.MsgCreateAggregatedKeyShareResponse - 8, // 15: fairyring.pep.Msg.RequestGeneralKeyshare:output_type -> fairyring.pep.MsgRequestGeneralKeyshareResponse - 10, // 16: fairyring.pep.Msg.GetGeneralKeyshare:output_type -> fairyring.pep.MsgGetGeneralKeyshareResponse - 12, // 17: fairyring.pep.Msg.RequestPrivateIdentity:output_type -> fairyring.pep.MsgRequestPrivateIdentityResponse - 14, // 18: fairyring.pep.Msg.GetPrivateKeyshares:output_type -> fairyring.pep.MsgGetPrivateKeysharesResponse - 16, // 19: fairyring.pep.Msg.RegisterContract:output_type -> fairyring.pep.MsgRegisterContractResponse - 11, // [11:20] is the sub-list for method output_type - 2, // [2:11] is the sub-list for method input_type + 17, // 11: fairyring.pep.Msg.UnregisterContract:input_type -> fairyring.pep.MsgUnregisterContract + 1, // 12: fairyring.pep.Msg.UpdateParams:output_type -> fairyring.pep.MsgUpdateParamsResponse + 4, // 13: fairyring.pep.Msg.SubmitEncryptedTx:output_type -> fairyring.pep.MsgSubmitEncryptedTxResponse + 4, // 14: fairyring.pep.Msg.SubmitGeneralEncryptedTx:output_type -> fairyring.pep.MsgSubmitEncryptedTxResponse + 6, // 15: fairyring.pep.Msg.CreateAggregatedKeyShare:output_type -> fairyring.pep.MsgCreateAggregatedKeyShareResponse + 8, // 16: fairyring.pep.Msg.RequestGeneralKeyshare:output_type -> fairyring.pep.MsgRequestGeneralKeyshareResponse + 10, // 17: fairyring.pep.Msg.GetGeneralKeyshare:output_type -> fairyring.pep.MsgGetGeneralKeyshareResponse + 12, // 18: fairyring.pep.Msg.RequestPrivateIdentity:output_type -> fairyring.pep.MsgRequestPrivateIdentityResponse + 14, // 19: fairyring.pep.Msg.GetPrivateKeyshares:output_type -> fairyring.pep.MsgGetPrivateKeysharesResponse + 16, // 20: fairyring.pep.Msg.RegisterContract:output_type -> fairyring.pep.MsgRegisterContractResponse + 18, // 21: fairyring.pep.Msg.UnregisterContract:output_type -> fairyring.pep.MsgUnregisterContractResponse + 12, // [12:22] is the sub-list for method output_type + 2, // [2:12] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name 2, // [2:2] is the sub-list for extension extendee 0, // [0:2] is the sub-list for field type_name @@ -8873,6 +9875,30 @@ func file_fairyring_pep_tx_proto_init() { return nil } } + file_fairyring_pep_tx_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgUnregisterContract); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fairyring_pep_tx_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgUnregisterContractResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -8880,7 +9906,7 @@ func file_fairyring_pep_tx_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_fairyring_pep_tx_proto_rawDesc, NumEnums: 0, - NumMessages: 17, + NumMessages: 19, NumExtensions: 0, NumServices: 1, }, diff --git a/api/fairyring/pep/tx_grpc.pb.go b/api/fairyring/pep/tx_grpc.pb.go index 3e91ea1e..b712f03b 100644 --- a/api/fairyring/pep/tx_grpc.pb.go +++ b/api/fairyring/pep/tx_grpc.pb.go @@ -28,6 +28,7 @@ const ( Msg_RequestPrivateIdentity_FullMethodName = "/fairyring.pep.Msg/RequestPrivateIdentity" Msg_GetPrivateKeyshares_FullMethodName = "/fairyring.pep.Msg/GetPrivateKeyshares" Msg_RegisterContract_FullMethodName = "/fairyring.pep.Msg/RegisterContract" + Msg_UnregisterContract_FullMethodName = "/fairyring.pep.Msg/UnregisterContract" ) // MsgClient is the client API for Msg service. @@ -46,6 +47,7 @@ type MsgClient interface { RequestPrivateIdentity(ctx context.Context, in *MsgRequestPrivateIdentity, opts ...grpc.CallOption) (*MsgRequestPrivateIdentityResponse, error) GetPrivateKeyshares(ctx context.Context, in *MsgGetPrivateKeyshares, opts ...grpc.CallOption) (*MsgGetPrivateKeysharesResponse, error) RegisterContract(ctx context.Context, in *MsgRegisterContract, opts ...grpc.CallOption) (*MsgRegisterContractResponse, error) + UnregisterContract(ctx context.Context, in *MsgUnregisterContract, opts ...grpc.CallOption) (*MsgUnregisterContractResponse, error) } type msgClient struct { @@ -137,6 +139,15 @@ func (c *msgClient) RegisterContract(ctx context.Context, in *MsgRegisterContrac return out, nil } +func (c *msgClient) UnregisterContract(ctx context.Context, in *MsgUnregisterContract, opts ...grpc.CallOption) (*MsgUnregisterContractResponse, error) { + out := new(MsgUnregisterContractResponse) + err := c.cc.Invoke(ctx, Msg_UnregisterContract_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. // All implementations must embed UnimplementedMsgServer // for forward compatibility @@ -153,6 +164,7 @@ type MsgServer interface { RequestPrivateIdentity(context.Context, *MsgRequestPrivateIdentity) (*MsgRequestPrivateIdentityResponse, error) GetPrivateKeyshares(context.Context, *MsgGetPrivateKeyshares) (*MsgGetPrivateKeysharesResponse, error) RegisterContract(context.Context, *MsgRegisterContract) (*MsgRegisterContractResponse, error) + UnregisterContract(context.Context, *MsgUnregisterContract) (*MsgUnregisterContractResponse, error) mustEmbedUnimplementedMsgServer() } @@ -187,6 +199,9 @@ func (UnimplementedMsgServer) GetPrivateKeyshares(context.Context, *MsgGetPrivat func (UnimplementedMsgServer) RegisterContract(context.Context, *MsgRegisterContract) (*MsgRegisterContractResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RegisterContract not implemented") } +func (UnimplementedMsgServer) UnregisterContract(context.Context, *MsgUnregisterContract) (*MsgUnregisterContractResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UnregisterContract not implemented") +} func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {} // UnsafeMsgServer may be embedded to opt out of forward compatibility for this service. @@ -362,6 +377,24 @@ func _Msg_RegisterContract_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +func _Msg_UnregisterContract_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUnregisterContract) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UnregisterContract(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Msg_UnregisterContract_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UnregisterContract(ctx, req.(*MsgUnregisterContract)) + } + return interceptor(ctx, in, info, handler) +} + // Msg_ServiceDesc is the grpc.ServiceDesc for Msg service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -405,6 +438,10 @@ var Msg_ServiceDesc = grpc.ServiceDesc{ MethodName: "RegisterContract", Handler: _Msg_RegisterContract_Handler, }, + { + MethodName: "UnregisterContract", + Handler: _Msg_UnregisterContract_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "fairyring/pep/tx.proto", diff --git a/proto/fairyring/pep/tx.proto b/proto/fairyring/pep/tx.proto index 979e48fd..9fcf4b9e 100644 --- a/proto/fairyring/pep/tx.proto +++ b/proto/fairyring/pep/tx.proto @@ -32,6 +32,7 @@ service Msg { rpc RequestPrivateIdentity (MsgRequestPrivateIdentity ) returns (MsgRequestPrivateIdentityResponse ); rpc GetPrivateKeyshares (MsgGetPrivateKeyshares ) returns (MsgGetPrivateKeysharesResponse ); rpc RegisterContract (MsgRegisterContract ) returns (MsgRegisterContractResponse ); + rpc UnregisterContract (MsgUnregisterContract ) returns (MsgUnregisterContractResponse ); } // MsgUpdateParams is the Msg/UpdateParams request type. message MsgUpdateParams { @@ -122,4 +123,13 @@ message MsgRegisterContract { string identity = 3; } -message MsgRegisterContractResponse {} \ No newline at end of file +message MsgRegisterContractResponse {} + +message MsgUnregisterContract { + option (cosmos.msg.v1.signer) = "creator"; + string creator = 1; + string contract_address = 2; + string identity = 3; +} + +message MsgUnregisterContractResponse {} \ No newline at end of file diff --git a/scripts/tests/pep.sh b/scripts/tests/pep.sh index 01be7002..84d484fe 100755 --- a/scripts/tests/pep.sh +++ b/scripts/tests/pep.sh @@ -26,6 +26,7 @@ WALLET_1=$($BINARY keys show wallet1 -a --keyring-backend test --home $CHAIN_DIR VALIDATOR_1=$($BINARY keys show val1 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_1) WALLET_2=$($BINARY keys show wallet2 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_2) VALIDATOR_2=$($BINARY keys show val2 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_2) +WALLET_3=$($BINARY keys show wallet3 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_1) GENERATED_SHARE=$1 @@ -54,6 +55,14 @@ wait_for_tx () { echo "$RESULT" } +wait_for_tx_source () { + sleep $BLOCK_TIME + sleep $BLOCK_TIME + local TXHASH=$(echo "$1" | jq -r '.txhash') + RESULT=$($BINARY q tx --type=hash $TXHASH --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE -o json) + echo "$RESULT" +} + echo "Query new account pep nonce from pep module on chain fairyring_test_2" RESULT=$($BINARY query pep show-pep-nonce $VALIDATOR_2 --home $CHAIN_DIR/$CHAINID_2 --chain-id $CHAINID_2 --node $CHAIN2_NODE -o json) VALIDATOR_PEP_NONCE=$(echo "$RESULT" | jq -r '.pepNonce.nonce') @@ -843,12 +852,38 @@ sleep 10 REQ_ID="fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/contract123" CONTRACT_ADDR="fairy14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9stsyf7v" +echo "Trying to registering contract with unauthorized address" +RESULT=$($BINARY tx pep register-contract $CONTRACT_ADDR $REQ_ID --from $WALLET_3 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT +RESULT=$(wait_for_tx_source $RESULT) + +ERROR_MSG=$(echo "$RESULT" | jq -r '.raw_log') +if [[ "$ERROR_MSG" != *"unautorized registration; only cretor and admin can register"* ]]; then + echo "ERROR: '$ERROR_MSG'" + echo "ERROR MESSAGE: $(echo "$RESULT" | jq -r '.raw_log')" + exit 1 +fi + + echo "Registering contract with identity" RESULT=$($BINARY tx pep register-contract $CONTRACT_ADDR $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) check_tx_code $RESULT +RESULT=$(wait_for_tx_source $RESULT) sleep 10 +echo "Trying to unregistering contract with unauthorized address" +RESULT=$($BINARY tx pep unregister-contract $CONTRACT_ADDR $REQ_ID --from $WALLET_3 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT +RESULT=$(wait_for_tx_source $RESULT) +ERROR_MSG=$(echo "$RESULT" | jq -r '.raw_log') + +if [[ "$ERROR_MSG" != *"unautorized deregistration; only cretor and admin can deregister"* ]]; then + echo "ERROR: '$ERROR_MSG'" + echo "ERROR MESSAGE: $(echo "$RESULT" | jq -r '.raw_log')" + exit 1 +fi + echo "Request Generation of Aggr keyshare" RESULT=$($BINARY tx pep get-general-keyshare $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) echo "$RESULT" diff --git a/x/pep/client/cli/tx.go b/x/pep/client/cli/tx.go index 46a211e3..a27be67f 100644 --- a/x/pep/client/cli/tx.go +++ b/x/pep/client/cli/tx.go @@ -33,6 +33,7 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand(CmdRequestPrivateKeyshare()) cmd.AddCommand(CmdGetPrivateKeyshare()) cmd.AddCommand(CmdRegisterContract()) + cmd.AddCommand(CmdUnregisterContract()) // this line is used by starport scaffolding # 1 return cmd diff --git a/x/pep/client/cli/tx_unregister_contract.go b/x/pep/client/cli/tx_unregister_contract.go new file mode 100644 index 00000000..fb0dd961 --- /dev/null +++ b/x/pep/client/cli/tx_unregister_contract.go @@ -0,0 +1,41 @@ +package cli + +import ( + "strconv" + + "github.com/Fairblock/fairyring/x/pep/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/spf13/cobra" +) + +var _ = strconv.Itoa(0) + +func CmdUnregisterContract() *cobra.Command { + cmd := &cobra.Command{ + Use: "unregister-contract [contract-address] [identity]", + Short: "Broadcast message unregister-contract", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := types.NewMsgUnregisterContract( + clientCtx.GetFromAddress().String(), + args[0], + args[1], + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/pep/keeper/contract.go b/x/pep/keeper/contract.go index bf4e0f9f..0d585f25 100644 --- a/x/pep/keeper/contract.go +++ b/x/pep/keeper/contract.go @@ -21,6 +21,13 @@ func (k Keeper) SetContractEntry(ctx context.Context, contract types.RegisteredC store.Set([]byte(contract.Identity), b) } +// RemoveContractEntry removes a specific contract entry in the store by identity +func (k Keeper) RemoveContractEntry(ctx context.Context, identity string) { + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.ContractKeyPrefix)) + store.Delete([]byte(identity)) +} + // GetContractEntriesByID returns a the list of contracts for an identity func (k Keeper) GetContractEntriesByID( ctx context.Context, diff --git a/x/pep/keeper/msg_unregister_contract.go b/x/pep/keeper/msg_unregister_contract.go new file mode 100644 index 00000000..9d36f242 --- /dev/null +++ b/x/pep/keeper/msg_unregister_contract.go @@ -0,0 +1,56 @@ +package keeper + +import ( + "context" + "errors" + + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (k msgServer) UnregisterContract( + goCtx context.Context, + msg *types.MsgUnregisterContract, +) (*types.MsgUnregisterContractResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + contracAddr, err := sdk.AccAddressFromBech32(msg.ContractAddress) + if err != nil { + return nil, errors.New("invalid contract address") + } + + contractInfo := k.wasmKeeper.GetContractInfo(ctx, contracAddr) + if contractInfo == nil { + return nil, errors.New("contract information not found") + } + + if msg.Creator != contractInfo.Admin && msg.Creator != contractInfo.Creator { + return nil, errors.New("unautorized deregistration; only cretor and admin can deregister") + } + + entry, found := k.GetContractEntriesByID(ctx, msg.Identity) + contracts := make([]*types.ContractDetails, 0) + detailsFound := false + + if found && len(entry.Contracts) != 0 { + for _, c := range entry.Contracts { + if c.ContractAddress == msg.ContractAddress { + detailsFound = true + } else { + contracts = append(contracts, c) + } + } + } else { + return &types.MsgUnregisterContractResponse{}, + errors.New("no entry found for the provided identity") + } + + if detailsFound { + entry.Contracts = contracts + k.SetContractEntry(ctx, entry) + return &types.MsgUnregisterContractResponse{}, nil + } + + return &types.MsgUnregisterContractResponse{}, + errors.New("contract not found in the list of registered contracts") +} diff --git a/x/pep/module/module.go b/x/pep/module/module.go index 86bcb902..12a39e1e 100644 --- a/x/pep/module/module.go +++ b/x/pep/module/module.go @@ -293,6 +293,10 @@ func (am AppModule) BeginBlock(cctx context.Context) error { } } + if found { + am.keeper.RemoveContractEntry(ctx, entry.Identity) + } + if entry.TxList == nil { am.keeper.Logger().Info("No encrypted txs found for entry with req-id: ", entry.RequestId) am.keeper.RemoveExecutionQueueEntry(ctx, entry.Identity) diff --git a/x/pep/types/msg_unregister_contract.go b/x/pep/types/msg_unregister_contract.go new file mode 100644 index 00000000..fd01bdae --- /dev/null +++ b/x/pep/types/msg_unregister_contract.go @@ -0,0 +1,33 @@ +package types + +import ( + sdkioerrors "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const TypeMsgUnregisterContract = "unregister_contract" + +var _ sdk.Msg = &MsgRegisterContract{} + +func NewMsgUnregisterContract(creator string, contractAddr string, identity string) *MsgUnregisterContract { + return &MsgUnregisterContract{ + Creator: creator, + ContractAddress: contractAddr, + Identity: identity, + } +} + +func (msg *MsgUnregisterContract) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return sdkioerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) + } + + _, err = sdk.AccAddressFromBech32(msg.ContractAddress) + if err != nil { + return sdkioerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid contract address (%s)", err) + } + + return nil +} diff --git a/x/pep/types/tx.pb.go b/x/pep/types/tx.pb.go index be95dc58..3ef57b7e 100644 --- a/x/pep/types/tx.pb.go +++ b/x/pep/types/tx.pb.go @@ -862,6 +862,102 @@ func (m *MsgRegisterContractResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgRegisterContractResponse proto.InternalMessageInfo +type MsgUnregisterContract struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + ContractAddress string `protobuf:"bytes,2,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"` + Identity string `protobuf:"bytes,3,opt,name=identity,proto3" json:"identity,omitempty"` +} + +func (m *MsgUnregisterContract) Reset() { *m = MsgUnregisterContract{} } +func (m *MsgUnregisterContract) String() string { return proto.CompactTextString(m) } +func (*MsgUnregisterContract) ProtoMessage() {} +func (*MsgUnregisterContract) Descriptor() ([]byte, []int) { + return fileDescriptor_f6953e463911e1ec, []int{17} +} +func (m *MsgUnregisterContract) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUnregisterContract) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUnregisterContract.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 *MsgUnregisterContract) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUnregisterContract.Merge(m, src) +} +func (m *MsgUnregisterContract) XXX_Size() int { + return m.Size() +} +func (m *MsgUnregisterContract) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUnregisterContract.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUnregisterContract proto.InternalMessageInfo + +func (m *MsgUnregisterContract) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *MsgUnregisterContract) GetContractAddress() string { + if m != nil { + return m.ContractAddress + } + return "" +} + +func (m *MsgUnregisterContract) GetIdentity() string { + if m != nil { + return m.Identity + } + return "" +} + +type MsgUnregisterContractResponse struct { +} + +func (m *MsgUnregisterContractResponse) Reset() { *m = MsgUnregisterContractResponse{} } +func (m *MsgUnregisterContractResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUnregisterContractResponse) ProtoMessage() {} +func (*MsgUnregisterContractResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f6953e463911e1ec, []int{18} +} +func (m *MsgUnregisterContractResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUnregisterContractResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUnregisterContractResponse.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 *MsgUnregisterContractResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUnregisterContractResponse.Merge(m, src) +} +func (m *MsgUnregisterContractResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUnregisterContractResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUnregisterContractResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUnregisterContractResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgUpdateParams)(nil), "fairyring.pep.MsgUpdateParams") proto.RegisterType((*MsgUpdateParamsResponse)(nil), "fairyring.pep.MsgUpdateParamsResponse") @@ -880,70 +976,74 @@ func init() { proto.RegisterType((*MsgGetPrivateKeysharesResponse)(nil), "fairyring.pep.MsgGetPrivateKeysharesResponse") proto.RegisterType((*MsgRegisterContract)(nil), "fairyring.pep.MsgRegisterContract") proto.RegisterType((*MsgRegisterContractResponse)(nil), "fairyring.pep.MsgRegisterContractResponse") + proto.RegisterType((*MsgUnregisterContract)(nil), "fairyring.pep.MsgUnregisterContract") + proto.RegisterType((*MsgUnregisterContractResponse)(nil), "fairyring.pep.MsgUnregisterContractResponse") } func init() { proto.RegisterFile("fairyring/pep/tx.proto", fileDescriptor_f6953e463911e1ec) } var fileDescriptor_f6953e463911e1ec = []byte{ - // 919 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcf, 0x73, 0xdb, 0x44, - 0x14, 0x8e, 0x92, 0x34, 0xc5, 0xaf, 0x85, 0x34, 0x6a, 0x92, 0x3a, 0x82, 0x2a, 0xc1, 0xa5, 0x8c, - 0x31, 0xad, 0x45, 0x02, 0xc3, 0x30, 0xb9, 0xd5, 0x0d, 0xa4, 0x9d, 0x8e, 0x67, 0x32, 0x0a, 0x74, - 0x06, 0x2e, 0x9e, 0x95, 0xf4, 0xba, 0xd6, 0x24, 0xb6, 0x94, 0xdd, 0x75, 0x88, 0x38, 0x75, 0x18, - 0x4e, 0x9c, 0x38, 0xf2, 0x07, 0x70, 0xe0, 0x98, 0x03, 0x7f, 0x44, 0x0f, 0x1c, 0x3a, 0x9c, 0x38, - 0x01, 0x13, 0x1f, 0xf2, 0x6f, 0x30, 0x92, 0x56, 0x72, 0xac, 0x1f, 0x8e, 0xd3, 0x4b, 0xe2, 0xdd, - 0xf7, 0xed, 0xfb, 0xbe, 0xef, 0x59, 0xfb, 0x59, 0xb0, 0xfa, 0x82, 0xb8, 0x2c, 0x60, 0x6e, 0x9f, - 0x1a, 0x3e, 0xfa, 0x86, 0x38, 0x69, 0xfa, 0xcc, 0x13, 0x9e, 0xfa, 0x76, 0xba, 0xdf, 0xf4, 0xd1, - 0xd7, 0x96, 0x48, 0xcf, 0xed, 0x7b, 0x46, 0xf4, 0x37, 0x46, 0x68, 0x77, 0x6c, 0x8f, 0xf7, 0x3c, - 0x6e, 0xf4, 0x38, 0x35, 0x8e, 0x37, 0xc3, 0x7f, 0xb2, 0xb0, 0x16, 0x17, 0x3a, 0xd1, 0xca, 0x88, - 0x17, 0xb2, 0xa4, 0x53, 0xcf, 0xa3, 0x87, 0x68, 0x44, 0x2b, 0x6b, 0xf0, 0xc2, 0x70, 0x06, 0x8c, - 0x08, 0xd7, 0xeb, 0xcb, 0xfa, 0x32, 0xf5, 0xa8, 0x17, 0x9f, 0x0b, 0x3f, 0xc9, 0x5d, 0x6d, 0x5c, - 0xa3, 0x4f, 0x18, 0xe9, 0x25, 0x1d, 0xeb, 0xe3, 0x35, 0x42, 0x29, 0x43, 0x4a, 0x04, 0x3a, 0x9d, - 0x03, 0x0c, 0x3a, 0xbc, 0x4b, 0x18, 0x26, 0xdc, 0x52, 0xaf, 0x45, 0x38, 0x1a, 0xc7, 0x9b, 0x16, - 0x0a, 0xb2, 0x69, 0xd8, 0x9e, 0x2b, 0xb9, 0x6b, 0x7f, 0x2a, 0xb0, 0xd8, 0xe6, 0xf4, 0x1b, 0xdf, - 0x21, 0x02, 0xf7, 0x22, 0x0e, 0xf5, 0x73, 0xa8, 0x90, 0x81, 0xe8, 0x7a, 0xcc, 0x15, 0x41, 0x55, - 0xd9, 0x50, 0xea, 0x95, 0x56, 0xf5, 0xaf, 0x3f, 0x1e, 0x2e, 0x4b, 0x53, 0x8f, 0x1c, 0x87, 0x21, - 0xe7, 0xfb, 0x22, 0xe4, 0x37, 0x47, 0x50, 0xf5, 0x0b, 0x58, 0x88, 0x55, 0x56, 0x67, 0x37, 0x94, - 0xfa, 0x8d, 0xad, 0x95, 0xe6, 0xd8, 0x38, 0x9b, 0x71, 0xfb, 0x56, 0xe5, 0xd5, 0x3f, 0xeb, 0x33, - 0xbf, 0x9f, 0x9f, 0x36, 0x14, 0x53, 0xe2, 0xb7, 0x77, 0x7f, 0x3c, 0x3f, 0x6d, 0x8c, 0x3a, 0xfd, - 0x7c, 0x7e, 0xda, 0xf8, 0x8c, 0xba, 0xa2, 0x3b, 0xb0, 0x9a, 0xb6, 0xd7, 0x33, 0xbe, 0x22, 0x2e, - 0xb3, 0x0e, 0x3d, 0xfb, 0xc0, 0x18, 0xf9, 0x3e, 0x89, 0x9c, 0x67, 0xa4, 0xd7, 0xd6, 0xe0, 0x4e, - 0x66, 0xcb, 0x44, 0xee, 0x7b, 0x7d, 0x8e, 0xb5, 0x97, 0x0a, 0x2c, 0xb7, 0x39, 0xdd, 0x1f, 0x58, - 0x3d, 0x57, 0x7c, 0xd9, 0xb7, 0x59, 0xe0, 0x0b, 0x74, 0xbe, 0x3e, 0x51, 0xab, 0x70, 0xdd, 0x66, - 0x48, 0x84, 0xc7, 0x62, 0xb3, 0x66, 0xb2, 0x54, 0x55, 0x98, 0x77, 0x88, 0x20, 0x91, 0x9d, 0x8a, - 0x19, 0x7d, 0x56, 0x1f, 0xc0, 0x92, 0x20, 0x8c, 0xa2, 0x68, 0x85, 0x82, 0x9e, 0xa0, 0x4b, 0xbb, - 0xa2, 0x3a, 0xb7, 0xa1, 0xd4, 0xe7, 0xcd, 0x7c, 0x61, 0xfb, 0x66, 0x68, 0x2c, 0xe9, 0x57, 0xf3, - 0xe1, 0xdd, 0x54, 0xc1, 0x2e, 0xf6, 0x91, 0x91, 0xc3, 0x37, 0x17, 0xb2, 0x02, 0x0b, 0x0c, 0x8f, - 0x3a, 0xae, 0x13, 0xb1, 0x57, 0xcc, 0x6b, 0x0c, 0x8f, 0x9e, 0x3a, 0x19, 0x46, 0x1d, 0xde, 0x2b, - 0xf2, 0x9c, 0x0e, 0xe5, 0x28, 0x52, 0xf4, 0x38, 0x44, 0xe3, 0xa3, 0xf4, 0x29, 0x7a, 0x86, 0xc1, - 0x7e, 0xf8, 0x0c, 0x4d, 0x50, 0xb4, 0x0a, 0x0b, 0xdd, 0xd8, 0xfb, 0x6c, 0xe4, 0x5d, 0xae, 0x52, - 0xa5, 0x73, 0x23, 0xa5, 0x19, 0x49, 0xf7, 0xe1, 0xde, 0x04, 0xca, 0x54, 0xd9, 0x6f, 0x0a, 0xac, - 0xb5, 0x39, 0x35, 0xf1, 0x68, 0x80, 0x3c, 0x99, 0xd6, 0x33, 0x0c, 0xf8, 0x25, 0xc2, 0x9e, 0xc0, - 0x22, 0x72, 0xe1, 0xf6, 0xa2, 0xdb, 0xe0, 0xe0, 0x21, 0x09, 0xe4, 0xd3, 0xb8, 0xd6, 0x8c, 0xaf, - 0x61, 0x33, 0xb9, 0x86, 0xcd, 0x1d, 0x79, 0x0d, 0x5b, 0xf3, 0xbf, 0xfe, 0xbb, 0xae, 0x98, 0xef, - 0xa4, 0xe7, 0x76, 0xc2, 0x63, 0xd3, 0x0d, 0x78, 0x1b, 0xde, 0x2f, 0x55, 0x99, 0x78, 0xb9, 0xd0, - 0x49, 0xb9, 0xd0, 0xa9, 0xf6, 0x1c, 0x56, 0xda, 0x9c, 0xee, 0xe2, 0x15, 0xdc, 0x8d, 0x3a, 0xcd, - 0x96, 0x6b, 0x5a, 0x87, 0xbb, 0x85, 0x7d, 0xd3, 0xd9, 0x7e, 0x7b, 0x71, 0xb4, 0x7b, 0xcc, 0x3d, - 0x26, 0x02, 0x9f, 0x3a, 0xd8, 0x17, 0xe1, 0x2d, 0x2e, 0x27, 0x5f, 0x86, 0x98, 0x6e, 0x12, 0xf7, - 0xd8, 0x3c, 0x32, 0xad, 0x2f, 0x9b, 0xc7, 0xf7, 0xb0, 0x1a, 0xeb, 0x96, 0xe7, 0x12, 0xdd, 0xfc, - 0xaa, 0x9a, 0xd4, 0x75, 0xb8, 0xc1, 0xd1, 0xf6, 0x3b, 0xfe, 0xc0, 0x3a, 0xc0, 0x40, 0x7e, 0x7f, - 0x10, 0x6e, 0xed, 0x45, 0x3b, 0x19, 0xd1, 0x1b, 0xa0, 0x17, 0x13, 0xa7, 0x13, 0xfb, 0x49, 0x81, - 0xdb, 0x91, 0x2f, 0xea, 0x72, 0x81, 0xec, 0xb1, 0xd7, 0x17, 0x8c, 0xd8, 0x62, 0x82, 0xb0, 0x8f, - 0xe0, 0x96, 0x2d, 0x51, 0x1d, 0x12, 0x27, 0xa6, 0xd4, 0xb8, 0x98, 0xec, 0xcb, 0x20, 0x55, 0x35, - 0x78, 0xcb, 0x95, 0x23, 0x92, 0x52, 0xd3, 0x75, 0x46, 0xe8, 0xdd, 0xe8, 0xba, 0x66, 0x55, 0x24, - 0x2a, 0xb7, 0x86, 0xd7, 0x61, 0xae, 0xcd, 0xa9, 0xfa, 0x1c, 0x6e, 0x8e, 0x05, 0xba, 0x9e, 0x09, - 0xe2, 0x4c, 0x44, 0x6a, 0x1f, 0x4e, 0xae, 0xa7, 0xdf, 0x1b, 0xc2, 0x52, 0x3e, 0x3e, 0xef, 0xe5, - 0x0f, 0xe7, 0x40, 0xda, 0xc7, 0x53, 0x80, 0x52, 0x1a, 0x0e, 0xd5, 0xd2, 0x8c, 0x6c, 0x94, 0x35, - 0xca, 0x63, 0xaf, 0x46, 0xfa, 0x03, 0x54, 0x4b, 0x63, 0xb0, 0x80, 0xb4, 0x0c, 0xab, 0x6d, 0x4d, - 0x8f, 0x4d, 0xb9, 0x05, 0xac, 0x96, 0xe4, 0x5c, 0x3d, 0xdf, 0xad, 0x18, 0xa9, 0x7d, 0x32, 0x2d, - 0x32, 0x65, 0xed, 0x82, 0x5a, 0x90, 0x3d, 0x1f, 0xe4, 0xfb, 0xe4, 0x51, 0xda, 0x83, 0x69, 0x50, - 0x05, 0xfe, 0xb2, 0x61, 0x53, 0xee, 0x2f, 0x83, 0x9c, 0xe0, 0xaf, 0x2c, 0x65, 0x0e, 0xe0, 0x76, - 0x51, 0x96, 0xdc, 0x2f, 0x94, 0x9e, 0x85, 0x69, 0x0f, 0xa7, 0x82, 0xa5, 0x64, 0x16, 0xdc, 0xca, - 0x85, 0x43, 0xad, 0x48, 0xf2, 0x38, 0x46, 0x6b, 0x5c, 0x8e, 0x49, 0x38, 0xb4, 0x6b, 0x2f, 0xc3, - 0x97, 0xa6, 0xd6, 0xce, 0xab, 0x33, 0x5d, 0x79, 0x7d, 0xa6, 0x2b, 0xff, 0x9d, 0xe9, 0xca, 0x2f, - 0x43, 0x7d, 0xe6, 0xf5, 0x50, 0x9f, 0xf9, 0x7b, 0xa8, 0xcf, 0x7c, 0xd7, 0x98, 0xea, 0x9d, 0x49, - 0x04, 0x3e, 0x72, 0x6b, 0x21, 0xfa, 0x19, 0xfc, 0xf4, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x99, - 0x96, 0xdf, 0x02, 0x0b, 0x0b, 0x00, 0x00, + // 952 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x96, 0xcf, 0x6f, 0xdc, 0x44, + 0x14, 0xc7, 0xe3, 0x24, 0x0d, 0xdd, 0xd7, 0x42, 0x1a, 0x37, 0x49, 0x37, 0x86, 0x3a, 0x61, 0x4b, + 0xd1, 0xb2, 0xb4, 0x6b, 0x12, 0x10, 0x42, 0xb9, 0x75, 0x1b, 0x48, 0xab, 0x6a, 0xa5, 0x68, 0x43, + 0x2b, 0xc1, 0x65, 0x35, 0xb6, 0x5f, 0x67, 0xad, 0x64, 0x6d, 0x67, 0x66, 0x36, 0xc4, 0x9c, 0x2a, + 0x84, 0x38, 0x70, 0xe2, 0xc8, 0x1f, 0xc0, 0x81, 0x63, 0x0e, 0xfc, 0x11, 0x3d, 0x80, 0x54, 0x71, + 0xe2, 0x04, 0x28, 0x39, 0xe4, 0xdf, 0x40, 0xb6, 0xc7, 0xde, 0xac, 0x7f, 0x6c, 0x36, 0x5c, 0x7a, + 0x49, 0x76, 0x66, 0xbe, 0xf3, 0xbe, 0x9f, 0xf7, 0x3c, 0xf3, 0x6c, 0x58, 0x7e, 0x4e, 0x1c, 0x16, + 0x30, 0xc7, 0xa5, 0x86, 0x8f, 0xbe, 0x21, 0x8e, 0x9a, 0x3e, 0xf3, 0x84, 0xa7, 0xbe, 0x99, 0xce, + 0x37, 0x7d, 0xf4, 0xb5, 0x05, 0xd2, 0x77, 0x5c, 0xcf, 0x88, 0xfe, 0xc6, 0x0a, 0xed, 0x96, 0xe5, + 0xf1, 0xbe, 0xc7, 0x8d, 0x3e, 0xa7, 0xc6, 0xe1, 0x7a, 0xf8, 0x4f, 0x2e, 0xac, 0xc4, 0x0b, 0xdd, + 0x68, 0x64, 0xc4, 0x03, 0xb9, 0xa4, 0x53, 0xcf, 0xa3, 0xfb, 0x68, 0x44, 0x23, 0x73, 0xf0, 0xdc, + 0xb0, 0x07, 0x8c, 0x08, 0xc7, 0x73, 0xe5, 0xfa, 0x22, 0xf5, 0xa8, 0x17, 0xef, 0x0b, 0x7f, 0xc9, + 0x59, 0x6d, 0x94, 0xd1, 0x27, 0x8c, 0xf4, 0x93, 0x88, 0xf5, 0xd1, 0x35, 0x42, 0x29, 0x43, 0x4a, + 0x04, 0xda, 0xdd, 0x3d, 0x0c, 0xba, 0xbc, 0x47, 0x18, 0x26, 0xde, 0x92, 0xd7, 0x24, 0x1c, 0x8d, + 0xc3, 0x75, 0x13, 0x05, 0x59, 0x37, 0x2c, 0xcf, 0x91, 0xde, 0xb5, 0xdf, 0x15, 0x98, 0x6f, 0x73, + 0xfa, 0xd4, 0xb7, 0x89, 0xc0, 0x9d, 0xc8, 0x43, 0xfd, 0x14, 0x2a, 0x64, 0x20, 0x7a, 0x1e, 0x73, + 0x44, 0x50, 0x55, 0xd6, 0x94, 0x7a, 0xa5, 0x55, 0xfd, 0xf3, 0xb7, 0xfb, 0x8b, 0x32, 0xa9, 0x07, + 0xb6, 0xcd, 0x90, 0xf3, 0x5d, 0x11, 0xfa, 0x77, 0x86, 0x52, 0xf5, 0x33, 0x98, 0x8b, 0x29, 0xab, + 0xd3, 0x6b, 0x4a, 0xfd, 0xda, 0xc6, 0x52, 0x73, 0xa4, 0x9c, 0xcd, 0x38, 0x7c, 0xab, 0xf2, 0xf2, + 0xef, 0xd5, 0xa9, 0x5f, 0xcf, 0x8e, 0x1b, 0x4a, 0x47, 0xea, 0x37, 0xb7, 0xbf, 0x3b, 0x3b, 0x6e, + 0x0c, 0x23, 0xfd, 0x78, 0x76, 0xdc, 0xf8, 0x84, 0x3a, 0xa2, 0x37, 0x30, 0x9b, 0x96, 0xd7, 0x37, + 0xbe, 0x20, 0x0e, 0x33, 0xf7, 0x3d, 0x6b, 0xcf, 0x18, 0xe6, 0x7d, 0x14, 0x65, 0x9e, 0x41, 0xaf, + 0xad, 0xc0, 0xad, 0xcc, 0x54, 0x07, 0xb9, 0xef, 0xb9, 0x1c, 0x6b, 0x2f, 0x14, 0x58, 0x6c, 0x73, + 0xba, 0x3b, 0x30, 0xfb, 0x8e, 0xf8, 0xdc, 0xb5, 0x58, 0xe0, 0x0b, 0xb4, 0xbf, 0x3c, 0x52, 0xab, + 0xf0, 0x86, 0xc5, 0x90, 0x08, 0x8f, 0xc5, 0xc9, 0x76, 0x92, 0xa1, 0xaa, 0xc2, 0xac, 0x4d, 0x04, + 0x89, 0xd2, 0xa9, 0x74, 0xa2, 0xdf, 0xea, 0x3d, 0x58, 0x10, 0x84, 0x51, 0x14, 0xad, 0x10, 0xe8, + 0x11, 0x3a, 0xb4, 0x27, 0xaa, 0x33, 0x6b, 0x4a, 0x7d, 0xb6, 0x93, 0x5f, 0xd8, 0xbc, 0x1e, 0x26, + 0x96, 0xc4, 0xab, 0xf9, 0xf0, 0x76, 0x4a, 0xb0, 0x8d, 0x2e, 0x32, 0xb2, 0xff, 0xff, 0x41, 0x96, + 0x60, 0x8e, 0xe1, 0x41, 0xd7, 0xb1, 0x23, 0xf7, 0x4a, 0xe7, 0x0a, 0xc3, 0x83, 0xc7, 0x76, 0xc6, + 0x51, 0x87, 0x77, 0x8a, 0x72, 0x4e, 0x8b, 0x72, 0x10, 0x11, 0x3d, 0x0c, 0xd5, 0xf8, 0x20, 0x3d, + 0x45, 0x4f, 0x30, 0xd8, 0x0d, 0xcf, 0xd0, 0x18, 0xa2, 0x65, 0x98, 0xeb, 0xc5, 0xb9, 0x4f, 0x47, + 0xb9, 0xcb, 0x51, 0x4a, 0x3a, 0x33, 0x24, 0xcd, 0x20, 0xdd, 0x85, 0x3b, 0x63, 0x2c, 0x53, 0xb2, + 0x5f, 0x14, 0x58, 0x69, 0x73, 0xda, 0xc1, 0x83, 0x01, 0xf2, 0xa4, 0x5a, 0x4f, 0x30, 0xe0, 0x17, + 0x80, 0x3d, 0x82, 0x79, 0xe4, 0xc2, 0xe9, 0x47, 0xb7, 0xc1, 0xc6, 0x7d, 0x12, 0xc8, 0xd3, 0xb8, + 0xd2, 0x8c, 0xaf, 0x61, 0x33, 0xb9, 0x86, 0xcd, 0x2d, 0x79, 0x0d, 0x5b, 0xb3, 0x3f, 0xff, 0xb3, + 0xaa, 0x74, 0xde, 0x4a, 0xf7, 0x6d, 0x85, 0xdb, 0x26, 0x2b, 0xf0, 0x26, 0xbc, 0x5b, 0x4a, 0x99, + 0xe4, 0x72, 0x2e, 0x92, 0x72, 0x2e, 0x52, 0xed, 0x19, 0x2c, 0xb5, 0x39, 0xdd, 0xc6, 0x4b, 0x64, + 0x37, 0x8c, 0x34, 0x5d, 0xce, 0xb4, 0x0a, 0xb7, 0x0b, 0xe3, 0xa6, 0xb5, 0xfd, 0xea, 0x7c, 0x69, + 0x77, 0x98, 0x73, 0x48, 0x04, 0x3e, 0xb6, 0xd1, 0x15, 0xe1, 0x2d, 0x2e, 0x37, 0x5f, 0x84, 0xd8, + 0x6e, 0x9c, 0xf7, 0x48, 0x3d, 0x32, 0xa1, 0x2f, 0xaa, 0xc7, 0x37, 0xb0, 0x1c, 0x73, 0xcb, 0x7d, + 0x09, 0x37, 0xbf, 0x2c, 0x93, 0xba, 0x0a, 0xd7, 0x38, 0x5a, 0x7e, 0xd7, 0x1f, 0x98, 0x7b, 0x18, + 0xc8, 0xe7, 0x07, 0xe1, 0xd4, 0x4e, 0x34, 0x93, 0x81, 0x5e, 0x03, 0xbd, 0xd8, 0x38, 0xad, 0xd8, + 0xf7, 0x0a, 0xdc, 0x8c, 0xf2, 0xa2, 0x0e, 0x17, 0xc8, 0x1e, 0x7a, 0xae, 0x60, 0xc4, 0x12, 0x63, + 0xc0, 0x3e, 0x80, 0x1b, 0x96, 0x54, 0x75, 0x49, 0xdc, 0x31, 0x25, 0xe3, 0x7c, 0x32, 0x2f, 0x1b, + 0xa9, 0xaa, 0xc1, 0x55, 0x47, 0x96, 0x48, 0xa2, 0xa6, 0xe3, 0x0c, 0xe8, 0xed, 0xe8, 0xba, 0x66, + 0x29, 0x52, 0xca, 0x1f, 0x94, 0xe8, 0x44, 0x3d, 0x75, 0xd9, 0x6b, 0xe6, 0x8c, 0x4f, 0x60, 0x9e, + 0x23, 0x21, 0xdd, 0xf8, 0xe3, 0x2a, 0xcc, 0xb4, 0x39, 0x55, 0x9f, 0xc1, 0xf5, 0x91, 0x57, 0x8f, + 0x9e, 0x79, 0x65, 0x64, 0x9a, 0xb9, 0xf6, 0xfe, 0xf8, 0xf5, 0xf4, 0x84, 0x21, 0x2c, 0xe4, 0x1b, + 0xfd, 0x9d, 0xfc, 0xe6, 0x9c, 0x48, 0xfb, 0x70, 0x02, 0x51, 0x6a, 0xc3, 0xa1, 0x5a, 0xda, 0xcd, + 0x1b, 0x65, 0x81, 0xf2, 0xda, 0xcb, 0x99, 0x7e, 0x0b, 0xd5, 0xd2, 0x86, 0x5d, 0x60, 0x5a, 0xa6, + 0xd5, 0x36, 0x26, 0xd7, 0xa6, 0xde, 0x02, 0x96, 0x4b, 0x3a, 0x72, 0x3d, 0x1f, 0xad, 0x58, 0xa9, + 0x7d, 0x34, 0xa9, 0x32, 0x75, 0xed, 0x81, 0x5a, 0xd0, 0x25, 0xdf, 0xcb, 0xc7, 0xc9, 0xab, 0xb4, + 0x7b, 0x93, 0xa8, 0x0a, 0xf2, 0xcb, 0xb6, 0xc5, 0xf2, 0xfc, 0x32, 0xca, 0x31, 0xf9, 0x95, 0xf5, + 0xc3, 0x3d, 0xb8, 0x59, 0xd4, 0xf5, 0xee, 0x16, 0xa2, 0x67, 0x65, 0xda, 0xfd, 0x89, 0x64, 0xa9, + 0x99, 0x09, 0x37, 0x72, 0x6d, 0xac, 0x56, 0x84, 0x3c, 0xaa, 0xd1, 0x1a, 0x17, 0x6b, 0xce, 0x3f, + 0xb0, 0x82, 0x26, 0x54, 0xf0, 0xc0, 0xf2, 0xaa, 0xa2, 0x07, 0x56, 0xde, 0x48, 0xb4, 0x2b, 0x2f, + 0xc2, 0x0f, 0xc9, 0xd6, 0xd6, 0xcb, 0x13, 0x5d, 0x79, 0x75, 0xa2, 0x2b, 0xff, 0x9e, 0xe8, 0xca, + 0x4f, 0xa7, 0xfa, 0xd4, 0xab, 0x53, 0x7d, 0xea, 0xaf, 0x53, 0x7d, 0xea, 0xeb, 0xc6, 0x44, 0xdf, + 0x91, 0x22, 0xf0, 0x91, 0x9b, 0x73, 0xd1, 0xa7, 0xc1, 0xc7, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, + 0xa6, 0x87, 0x12, 0xeb, 0x1f, 0x0c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -970,6 +1070,7 @@ type MsgClient interface { RequestPrivateIdentity(ctx context.Context, in *MsgRequestPrivateIdentity, opts ...grpc.CallOption) (*MsgRequestPrivateIdentityResponse, error) GetPrivateKeyshares(ctx context.Context, in *MsgGetPrivateKeyshares, opts ...grpc.CallOption) (*MsgGetPrivateKeysharesResponse, error) RegisterContract(ctx context.Context, in *MsgRegisterContract, opts ...grpc.CallOption) (*MsgRegisterContractResponse, error) + UnregisterContract(ctx context.Context, in *MsgUnregisterContract, opts ...grpc.CallOption) (*MsgUnregisterContractResponse, error) } type msgClient struct { @@ -1061,6 +1162,15 @@ func (c *msgClient) RegisterContract(ctx context.Context, in *MsgRegisterContrac return out, nil } +func (c *msgClient) UnregisterContract(ctx context.Context, in *MsgUnregisterContract, opts ...grpc.CallOption) (*MsgUnregisterContractResponse, error) { + out := new(MsgUnregisterContractResponse) + err := c.cc.Invoke(ctx, "/fairyring.pep.Msg/UnregisterContract", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // UpdateParams defines a (governance) operation for updating the module @@ -1075,6 +1185,7 @@ type MsgServer interface { RequestPrivateIdentity(context.Context, *MsgRequestPrivateIdentity) (*MsgRequestPrivateIdentityResponse, error) GetPrivateKeyshares(context.Context, *MsgGetPrivateKeyshares) (*MsgGetPrivateKeysharesResponse, error) RegisterContract(context.Context, *MsgRegisterContract) (*MsgRegisterContractResponse, error) + UnregisterContract(context.Context, *MsgUnregisterContract) (*MsgUnregisterContractResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -1108,6 +1219,9 @@ func (*UnimplementedMsgServer) GetPrivateKeyshares(ctx context.Context, req *Msg func (*UnimplementedMsgServer) RegisterContract(ctx context.Context, req *MsgRegisterContract) (*MsgRegisterContractResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RegisterContract not implemented") } +func (*UnimplementedMsgServer) UnregisterContract(ctx context.Context, req *MsgUnregisterContract) (*MsgUnregisterContractResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UnregisterContract not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -1275,6 +1389,24 @@ func _Msg_RegisterContract_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +func _Msg_UnregisterContract_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUnregisterContract) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UnregisterContract(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/fairyring.pep.Msg/UnregisterContract", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UnregisterContract(ctx, req.(*MsgUnregisterContract)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "fairyring.pep.Msg", HandlerType: (*MsgServer)(nil), @@ -1315,6 +1447,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "RegisterContract", Handler: _Msg_RegisterContract_Handler, }, + { + MethodName: "UnregisterContract", + Handler: _Msg_UnregisterContract_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "fairyring/pep/tx.proto", @@ -1895,6 +2031,73 @@ func (m *MsgRegisterContractResponse) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } +func (m *MsgUnregisterContract) 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 *MsgUnregisterContract) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUnregisterContract) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Identity) > 0 { + i -= len(m.Identity) + copy(dAtA[i:], m.Identity) + i = encodeVarintTx(dAtA, i, uint64(len(m.Identity))) + i-- + dAtA[i] = 0x1a + } + if len(m.ContractAddress) > 0 { + i -= len(m.ContractAddress) + copy(dAtA[i:], m.ContractAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.ContractAddress))) + i-- + dAtA[i] = 0x12 + } + 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] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUnregisterContractResponse) 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 *MsgUnregisterContractResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUnregisterContractResponse) 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 @@ -2159,6 +2362,36 @@ func (m *MsgRegisterContractResponse) Size() (n int) { return n } +func (m *MsgUnregisterContract) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ContractAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Identity) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUnregisterContractResponse) 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 } @@ -3826,6 +4059,202 @@ func (m *MsgRegisterContractResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgUnregisterContract) 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: MsgUnregisterContract: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUnregisterContract: 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 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 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", 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.ContractAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Identity", 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.Identity = 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 *MsgUnregisterContractResponse) 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: MsgUnregisterContractResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUnregisterContractResponse: 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 From 50b0bb46d21f032b02fd8052dbb1c57bb9c4ca68 Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Thu, 3 Oct 2024 23:36:41 +0530 Subject: [PATCH 28/41] removing local dependency on fairyring contract --- scripts/tests/fairyring_contract/Cargo.lock | 441 ++++++++++++++++++ scripts/tests/fairyring_contract/Cargo.toml | 2 +- .../artifacts/checksums.txt | 2 +- .../artifacts/fairyring_contract.wasm | Bin 202290 -> 202402 bytes .../optimized_contract.wasm | Bin 1373285 -> 0 bytes .../tests/fairyring_contract/src/contract.rs | 9 +- scripts/tests/fairyring_contract/src/msg.rs | 17 +- 7 files changed, 452 insertions(+), 19 deletions(-) delete mode 100644 scripts/tests/fairyring_contract/optimized_contract.wasm diff --git a/scripts/tests/fairyring_contract/Cargo.lock b/scripts/tests/fairyring_contract/Cargo.lock index 59374ffb..d7aff698 100644 --- a/scripts/tests/fairyring_contract/Cargo.lock +++ b/scripts/tests/fairyring_contract/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.11" @@ -147,12 +162,38 @@ dependencies = [ "rayon", ] +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + [[package]] name = "base16ct" version = "0.2.0" @@ -197,6 +238,9 @@ name = "bytes" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +dependencies = [ + "serde", +] [[package]] name = "cfg-if" @@ -210,6 +254,17 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "cosmos-sdk-proto" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2f63ab112b8c8e7b8a29c891adc48f43145beb21c0bfbf562957072c1e0beb" +dependencies = [ + "prost", + "prost-types", + "tendermint-proto", +] + [[package]] name = "cosmwasm-core" version = "2.1.4" @@ -434,6 +489,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivative" version = "2.2.0" @@ -545,6 +609,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "fairblock-proto" +version = "0.1.0" +source = "git+https://github.com/Fairblock/fairblock-rust/?branch=contract-callback#7a24f0d3cf3e4315f90e99567c5e4e01923d6c84" +dependencies = [ + "cosmos-sdk-proto", + "prost", + "prost-types", + "tonic", +] + [[package]] name = "fairyring_contract" version = "0.1.0" @@ -553,6 +628,7 @@ dependencies = [ "cosmwasm-std", "cw-multi-test", "cw-storage-plus", + "fairblock-proto", "prost", "prost-types", "schemars", @@ -576,6 +652,45 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "flex-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" +dependencies = [ + "paste", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -598,6 +713,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + [[package]] name = "group" version = "0.13.0" @@ -643,6 +764,40 @@ dependencies = [ "digest", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + [[package]] name = "itertools" version = "0.10.5" @@ -691,6 +846,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -701,6 +865,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.46" @@ -719,6 +889,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.20.1" @@ -746,12 +925,56 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "portable-atomic" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -879,6 +1102,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + [[package]] name = "rustc_version" version = "0.4.1" @@ -955,6 +1184,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.210" @@ -1022,6 +1260,15 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + [[package]] name = "syn" version = "1.0.109" @@ -1044,6 +1291,22 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tendermint-proto" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed14abe3b0502a3afe21ca74ca5cdd6c7e8d326d982c26f98a394445eb31d6e" +dependencies = [ + "bytes", + "flex-error", + "prost", + "prost-types", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + [[package]] name = "thiserror" version = "1.0.64" @@ -1064,6 +1327,120 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "pin-project-lite", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-trait", + "base64", + "bytes", + "http", + "http-body", + "http-body-util", + "percent-encoding", + "pin-project", + "prost", + "tokio-stream", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + [[package]] name = "typenum" version = "1.17.0" @@ -1094,6 +1471,70 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/scripts/tests/fairyring_contract/Cargo.toml b/scripts/tests/fairyring_contract/Cargo.toml index 5bf01601..ed0a8765 100644 --- a/scripts/tests/fairyring_contract/Cargo.toml +++ b/scripts/tests/fairyring_contract/Cargo.toml @@ -42,7 +42,7 @@ thiserror = "1.0" prost = "0.13.3" # Protobuf support prost-types = "0.13" # tonic = { version = "0.12.3", features = ["prost", "tls"] } -# fairblock-proto = { git = "https://github.com/Fairblock/fairblock-rust/", branch = "contract-callback" } +fairblock-proto = { git = "https://github.com/Fairblock/fairblock-rust/", branch = "contract-callback" } # getrandom = { version = "0.2", features = ["js"] } # mio = "1.0.2" # tokio = "1.40.0" diff --git a/scripts/tests/fairyring_contract/artifacts/checksums.txt b/scripts/tests/fairyring_contract/artifacts/checksums.txt index 7b54131d..d3f83ce4 100644 --- a/scripts/tests/fairyring_contract/artifacts/checksums.txt +++ b/scripts/tests/fairyring_contract/artifacts/checksums.txt @@ -1 +1 @@ -c935c52c556a28243a4c11f4bf94aedac9313df501e59538b79eb82de5e592a1 fairyring_contract.wasm +6868e236b02b69d77557e203908940e25b5ecc70a5649880399732f5e665301e fairyring_contract.wasm diff --git a/scripts/tests/fairyring_contract/artifacts/fairyring_contract.wasm b/scripts/tests/fairyring_contract/artifacts/fairyring_contract.wasm index e850ccefdcd39767e061680af871635670dc2f26..fb93167db202747851e1df4e6b8d10b0abb845ce 100644 GIT binary patch delta 24717 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 m1qx@if-ot+ItnERP}Q7g!Qqaf&vhC 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 S;o1HM&pkX5nA*n`+y4WrW8W|U diff --git a/scripts/tests/fairyring_contract/optimized_contract.wasm b/scripts/tests/fairyring_contract/optimized_contract.wasm deleted file mode 100644 index 1ae2ad0706683740caeea44f2acfecd45110398a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1373285 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 z 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Ⓢ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 Q^p}4=g|g>Yu-W_n0n(H1k^lez diff --git a/scripts/tests/fairyring_contract/src/contract.rs b/scripts/tests/fairyring_contract/src/contract.rs index 5db81700..cfb354ff 100644 --- a/scripts/tests/fairyring_contract/src/contract.rs +++ b/scripts/tests/fairyring_contract/src/contract.rs @@ -1,8 +1,9 @@ // contract.rs use cosmwasm_std::{attr, entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; use prost::Message; -use crate::msg::{ExecuteContractMsg, QueryMsg, QueryResponse, InstantiateMsg, QueryDecryptDataRequest, QueryDecryptDataResponse}; +use crate::msg::{ExecuteContractMsg, QueryMsg, QueryResponse, InstantiateMsg, QueryDecryptDataResponse as JsonDcryptData}; use crate::state::STORED_DATA; +use fairblock_proto::fairyring::pep::{QueryDecryptDataRequest, QueryDecryptDataResponse}; #[entry_point] pub fn execute( @@ -116,6 +117,10 @@ pub fn query_pep_decrypt( let x = QueryDecryptDataResponse::decode(&*vec_res) .expect("Failed to decode Protobuf message"); - let json_res = to_json_binary(&x)?; + let json_data = JsonDcryptData { + decrypted_data : x.decrypted_data, + }; + + let json_res = to_json_binary(&json_data)?; Ok(json_res) } diff --git a/scripts/tests/fairyring_contract/src/msg.rs b/scripts/tests/fairyring_contract/src/msg.rs index 5ab18319..afaaf379 100644 --- a/scripts/tests/fairyring_contract/src/msg.rs +++ b/scripts/tests/fairyring_contract/src/msg.rs @@ -32,22 +32,9 @@ pub struct QueryResponse { pub aggr_keyshare: String, } -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryDecryptDataRequest { - #[prost(string, tag="1")] - pub pubkey: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub aggr_keyshare: ::prost::alloc::string::String, - #[prost(string, tag="3")] - pub encrypted_data: ::prost::alloc::string::String, -} - -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message, Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct QueryDecryptDataResponse { - #[prost(string, tag="1")] - pub decrypted_data: ::prost::alloc::string::String, + pub decrypted_data: String, } // Instantiate message From 0b905dbac0776f3f3b8577bdc192dd763a3fd34d Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Fri, 4 Oct 2024 23:39:29 -0400 Subject: [PATCH 29/41] Add remaining queries unit tests --- x/pep/keeper/query_decrypt_data_test.go | 125 +++++++++++++ x/pep/keeper/query_keyshare.go | 23 ++- x/pep/keeper/query_keyshare_test.go | 171 ++++++++++++++++++ x/pep/keeper/query_latest_height_test.go | 57 ++++++ .../keeper/query_private_keyshare_req_test.go | 72 ++++++++ 5 files changed, 444 insertions(+), 4 deletions(-) create mode 100644 x/pep/keeper/query_decrypt_data_test.go create mode 100644 x/pep/keeper/query_keyshare_test.go create mode 100644 x/pep/keeper/query_latest_height_test.go create mode 100644 x/pep/keeper/query_private_keyshare_req_test.go diff --git a/x/pep/keeper/query_decrypt_data_test.go b/x/pep/keeper/query_decrypt_data_test.go new file mode 100644 index 00000000..14734d09 --- /dev/null +++ b/x/pep/keeper/query_decrypt_data_test.go @@ -0,0 +1,125 @@ +package keeper_test + +import ( + "bytes" + "encoding/hex" + enc "github.com/FairBlock/DistributedIBE/encryption" + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/shares" + commontypes "github.com/Fairblock/fairyring/x/common/types" + bls "github.com/drand/kyber-bls12381" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestDecryptDataQuerySingle(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + + out, err := random.GeneratePubKeyAndShares(1) + require.NoError(t, err) + + creator := out.GeneratedShare[0].ValidatorAddress + + encryptID := "testingID" + plainTextData := "TestingData" + + derived, err := shares.DeriveShare(out.GeneratedShare[0].Share, 1, encryptID) + require.NoError(t, err) + + suite := bls.NewBLS12381Suite() + publicKeyByte, err := hex.DecodeString(out.MasterPublicKey) + require.NoError(t, err) + + publicKeyPoint := suite.G1().Point() + err = publicKeyPoint.UnmarshalBinary(publicKeyByte) + require.NoError(t, err) + + var destCipherData bytes.Buffer + var plainTextBuffer bytes.Buffer + _, err = plainTextBuffer.WriteString(plainTextData) + require.NoError(t, err) + + err = enc.Encrypt(publicKeyPoint, []byte(encryptID), &destCipherData, &plainTextBuffer) + require.NoError(t, err) + + for _, tc := range []struct { + desc string + request *types.QueryDecryptDataRequest + response *types.QueryDecryptDataResponse + err error + errMsg string + }{ + { + desc: "WithPubKey", + request: &types.QueryDecryptDataRequest{ + Pubkey: out.MasterPublicKey, + AggrKeyshare: derived, + EncryptedData: hex.EncodeToString(destCipherData.Bytes()), + }, + response: &types.QueryDecryptDataResponse{ + DecryptedData: plainTextData, + }, + }, + { + desc: "WithoutPubKeyAndNoPubKeyOnChain", + request: &types.QueryDecryptDataRequest{ + AggrKeyshare: derived, + EncryptedData: hex.EncodeToString(destCipherData.Bytes()), + }, + errMsg: "pubkey not found", + }, + { + desc: "InvalidPubKey", + request: &types.QueryDecryptDataRequest{ + Pubkey: random.RandHex(8), + AggrKeyshare: derived, + EncryptedData: hex.EncodeToString(destCipherData.Bytes()), + }, + errMsg: "input string length must be equal to 48 bytes", + }, + { + desc: "InvalidAggrKeyShare", + request: &types.QueryDecryptDataRequest{ + Pubkey: out.MasterPublicKey, + AggrKeyshare: random.RandHex(8), + EncryptedData: hex.EncodeToString(destCipherData.Bytes()), + }, + errMsg: "input string length must be equal to 96 bytes", + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.DecryptData(wctx, tc.request) + if len(tc.errMsg) > 0 { + require.Equal(t, + nullify.Fill(err.Error()), + nullify.Fill(tc.errMsg)) + } else if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + + if tc.desc == "WithoutPubKeyAndNoPubKeyOnChain" { + keeper.SetActivePubKey(wctx, commontypes.ActivePublicKey{ + PublicKey: out.MasterPublicKey, + Creator: creator, + Expiry: 12346788888, + }) + } + }) + } +} diff --git a/x/pep/keeper/query_keyshare.go b/x/pep/keeper/query_keyshare.go index e3e3360c..d613f028 100644 --- a/x/pep/keeper/query_keyshare.go +++ b/x/pep/keeper/query_keyshare.go @@ -2,6 +2,9 @@ package keeper import ( "context" + "cosmossdk.io/store/prefix" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/Fairblock/fairyring/x/pep/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -31,12 +34,24 @@ func (k Keeper) KeyshareReqAll(c context.Context, req *types.QueryAllKeyshareReq ctx := sdk.UnwrapSDKContext(c) - entries := k.GetAllGenEncTxEntry(ctx) + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.GenEncTxKeyPrefix)) var keyshares []*types.GenEncTxExecutionQueue - for _, entry := range entries { - keyshares = append(keyshares, &entry) + + pageRes, err := query.Paginate(store, req.Pagination, func(key []byte, value []byte) error { + var keyshare types.GenEncTxExecutionQueue + if err := k.cdc.Unmarshal(value, &keyshare); err != nil { + return err + } + + keyshares = append(keyshares, &keyshare) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) } - return &types.QueryAllKeyshareResponse{Keyshares: keyshares}, nil + return &types.QueryAllKeyshareResponse{Keyshares: keyshares, Pagination: pageRes}, nil } diff --git a/x/pep/keeper/query_keyshare_test.go b/x/pep/keeper/query_keyshare_test.go new file mode 100644 index 00000000..616b0c4e --- /dev/null +++ b/x/pep/keeper/query_keyshare_test.go @@ -0,0 +1,171 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "github.com/cosmos/cosmos-sdk/types/query" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestKeyShareReqSingle(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + + out := createNGeneralEncryptedTxEntry(&keeper, wctx, 5) + + for _, tc := range []struct { + desc string + request *types.QueryKeyshareRequest + response *types.QueryKeyshareResponse + err error + errMsg string + }{ + { + desc: "First item", + request: &types.QueryKeyshareRequest{ + ReqId: out[0].RequestId, + }, + response: &types.QueryKeyshareResponse{ + Keyshare: &out[0], + }, + }, + { + desc: "Not found", + request: &types.QueryKeyshareRequest{ + ReqId: random.RandHex(64), + }, + err: status.Error(codes.NotFound, "not found"), + }, + { + desc: "Invalid request", + request: nil, + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.KeyshareReq(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + + }) + } +} + +func TestKeyshareReqAll(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNGeneralEncryptedTxEntry(&keeper, ctx, 5) + + resp, err := keeper.KeyshareReqAll(wctx, &types.QueryAllKeyshareRequest{ + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 0, + CountTotal: false, + }, + }) + require.NoError(t, err) + require.Equal(t, len(resp.Keyshares), len(msgs)) + + check := make([]types.GenEncTxExecutionQueue, len(resp.Keyshares)) + for i := range resp.Keyshares { + check[i] = *resp.Keyshares[i] + } + + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(check), + ) +} + +func TestKeyshareReqPaginated(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + msgs := createNGeneralEncryptedTxEntry(&keeper, ctx, 5) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllKeyshareRequest { + return &types.QueryAllKeyshareRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.KeyshareReqAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.Keyshares), step) + + check := make([]types.GenEncTxExecutionQueue, len(resp.Keyshares)) + for j := range resp.Keyshares { + check[j] = *resp.Keyshares[j] + } + + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(check), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.KeyshareReqAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.Keyshares), step) + + check := make([]types.GenEncTxExecutionQueue, len(resp.Keyshares)) + for j := range resp.Keyshares { + check[j] = *resp.Keyshares[j] + } + + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(check), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.KeyshareReqAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + + check := make([]types.GenEncTxExecutionQueue, len(resp.Keyshares)) + for j := range resp.Keyshares { + check[j] = *resp.Keyshares[j] + } + + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(check), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.KeyshareReqAll(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) + }) +} diff --git a/x/pep/keeper/query_latest_height_test.go b/x/pep/keeper/query_latest_height_test.go new file mode 100644 index 00000000..7edb3a60 --- /dev/null +++ b/x/pep/keeper/query_latest_height_test.go @@ -0,0 +1,57 @@ +package keeper_test + +import ( + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestLatestHeightQuery(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + + keeper.SetLatestHeight(wctx, "100") + + for _, tc := range []struct { + desc string + request *types.QueryLatestHeightRequest + response *types.QueryLatestHeightResponse + err error + }{ + { + desc: "ValidRequest", + request: &types.QueryLatestHeightRequest{}, + response: &types.QueryLatestHeightResponse{ + Height: 100, + }, + }, + { + desc: "InvalidRequest", + request: nil, + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.LatestHeight(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} diff --git a/x/pep/keeper/query_private_keyshare_req_test.go b/x/pep/keeper/query_private_keyshare_req_test.go new file mode 100644 index 00000000..9a596def --- /dev/null +++ b/x/pep/keeper/query_private_keyshare_req_test.go @@ -0,0 +1,72 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + types2 "github.com/Fairblock/fairyring/x/common/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "strconv" + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestShowPrivateKeyshareReq(t *testing.T) { + keeper, ctx := keepertest.PepKeeper(t) + wctx := sdk.UnwrapSDKContext(ctx) + + req := types.PrivateRequest{ + Creator: sample.AccAddress(), + ReqId: random.RandHex(16), + Pubkey: random.RandHex(96), + EncryptedKeyshares: make([]*types2.EncryptedKeyshare, 0), + } + + keeper.SetPrivateRequest(wctx, req) + + for _, tc := range []struct { + desc string + request *types.QueryShowPrivateKeyshareReqRequest + response *types.QueryShowPrivateKeyshareReqResponse + err error + }{ + { + desc: "ValidRequest", + request: &types.QueryShowPrivateKeyshareReqRequest{ + ReqId: req.ReqId, + }, + response: &types.QueryShowPrivateKeyshareReqResponse{ + Creator: req.Creator, + ReqId: req.ReqId, + Pubkey: req.Pubkey, + EncryptedKeyshares: req.EncryptedKeyshares, + }, + }, + { + desc: "InvalidRequest", + request: nil, + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.ShowPrivateKeyshareReq(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} From 0590365b046e8bc2208a94508626d3f57a1191dc Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Fri, 4 Oct 2024 23:39:44 -0400 Subject: [PATCH 30/41] Add msgs unit tests --- testutil/keeper/keyshare.go | 33 +++- testutil/keeper/pep.go | 34 ++++- .../msg_create_aggregated_key_share_test.go | 142 ++++++++++++++++++ x/pep/keeper/msg_submit_encrypted_tx.go | 20 +-- x/pep/keeper/msg_submit_encrypted_tx_test.go | 120 +++++++++++++++ x/pep/keeper/msg_submit_gen_enc_tx.go | 20 +-- x/pep/keeper/msg_submit_gen_enc_tx_test.go | 102 +++++++++++++ 7 files changed, 440 insertions(+), 31 deletions(-) create mode 100644 x/pep/keeper/msg_create_aggregated_key_share_test.go create mode 100644 x/pep/keeper/msg_submit_encrypted_tx_test.go create mode 100644 x/pep/keeper/msg_submit_gen_enc_tx_test.go diff --git a/testutil/keeper/keyshare.go b/testutil/keeper/keyshare.go index 7624f2c6..f384c632 100644 --- a/testutil/keeper/keyshare.go +++ b/testutil/keeper/keyshare.go @@ -15,16 +15,17 @@ import ( "github.com/cosmos/cosmos-sdk/runtime" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" + keeper2 "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" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" portkeeper "github.com/cosmos/ibc-go/v8/modules/core/05-port/keeper" ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" - "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "testing" @@ -44,6 +45,8 @@ func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context, pepkeeper.Keeper, stakingStoreKey := storetypes.NewKVStoreKey(stakingtypes.StoreKey) memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) pepMemStoreKey := storetypes.NewMemoryStoreKey(peptypes.MemStoreKey) + bankStoreKey := storetypes.NewKVStoreKey(banktypes.StoreKey) + authStoreKey := storetypes.NewKVStoreKey(authtypes.StoreKey) db := dbm.NewMemDB() stateStore := store.NewCommitMultiStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics()) @@ -52,6 +55,8 @@ func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context, pepkeeper.Keeper, stateStore.MountStoreWithDB(stakingStoreKey, storetypes.StoreTypeIAVL, db) stateStore.MountStoreWithDB(memStoreKey, storetypes.StoreTypeMemory, nil) stateStore.MountStoreWithDB(pepMemStoreKey, storetypes.StoreTypeMemory, nil) + stateStore.MountStoreWithDB(bankStoreKey, storetypes.StoreTypeIAVL, db) + stateStore.MountStoreWithDB(authStoreKey, storetypes.StoreTypeIAVL, db) require.NoError(t, stateStore.LoadLatestVersion()) registry := codectypes.NewInterfaceRegistry() @@ -66,13 +71,23 @@ func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context, pepkeeper.Keeper, pepScopedKeeper := pepCapabilityKeeper.ScopeToModule(ibcexported.ModuleName) pepPortKeeper := portkeeper.NewKeeper(pepScopedKeeper) - ctrl := gomock.NewController(t) - accountKeeper := stakingtestutil.NewMockAccountKeeper(ctrl) - accountKeeper.EXPECT().GetModuleAddress(stakingtypes.BondedPoolName).Return(bondedAcc.GetAddress()) - accountKeeper.EXPECT().GetModuleAddress(stakingtypes.NotBondedPoolName).Return(notBondedAcc.GetAddress()) - accountKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() + accountKeeper := keeper2.NewAccountKeeper( + appCodec, + runtime.NewKVStoreService(authStoreKey), + authtypes.ProtoBaseAccount, + make(map[string][]string, 0), + address.NewBech32Codec("cosmos"), + sdk.Bech32PrefixAccAddr, + authority.String(), + ) - bankKeeper := stakingtestutil.NewMockBankKeeper(ctrl) + bankKeeper := bankkeeper.NewBaseKeeper( + appCodec, runtime.NewKVStoreService(bankStoreKey), + accountKeeper, + make(map[string]bool, 0), + authority.String(), + log.NewNopLogger(), + ) pepKeeper := pepkeeper.NewKeeper( appCodec, @@ -86,6 +101,8 @@ func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context, pepkeeper.Keeper, }, pepScopedKeeper, accountKeeper, + bankKeeper, + nil, nil, ) diff --git a/testutil/keeper/pep.go b/testutil/keeper/pep.go index 79280efd..91397b40 100644 --- a/testutil/keeper/pep.go +++ b/testutil/keeper/pep.go @@ -1,6 +1,10 @@ package keeper import ( + "github.com/cosmos/cosmos-sdk/codec/address" + keeper2 "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" "testing" "cosmossdk.io/log" @@ -29,10 +33,15 @@ func PepKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { storeKey := storetypes.NewKVStoreKey(types.StoreKey) memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) + bankStoreKey := storetypes.NewKVStoreKey(banktypes.StoreKey) + authStoreKey := storetypes.NewKVStoreKey(authtypes.StoreKey) + db := dbm.NewMemDB() stateStore := store.NewCommitMultiStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics()) stateStore.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, db) stateStore.MountStoreWithDB(memStoreKey, storetypes.StoreTypeMemory, nil) + stateStore.MountStoreWithDB(bankStoreKey, storetypes.StoreTypeIAVL, db) + stateStore.MountStoreWithDB(authStoreKey, storetypes.StoreTypeIAVL, db) require.NoError(t, stateStore.LoadLatestVersion()) registry := codectypes.NewInterfaceRegistry() @@ -44,6 +53,24 @@ func PepKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { portKeeper := portkeeper.NewKeeper(scopedKeeper) // scopeModule := capabilityKeeper.ScopeToModule(types.ModuleName) + accountKeeper := keeper2.NewAccountKeeper( + appCodec, + runtime.NewKVStoreService(authStoreKey), + authtypes.ProtoBaseAccount, + make(map[string][]string, 0), + address.NewBech32Codec("cosmos"), + sdk.Bech32PrefixAccAddr, + authority.String(), + ) + + bankKeeper := bankkeeper.NewBaseKeeper( + appCodec, runtime.NewKVStoreService(bankStoreKey), + accountKeeper, + make(map[string]bool, 0), + authority.String(), + log.NewNopLogger(), + ) + k := keeper.NewKeeper( appCodec, runtime.NewKVStoreService(storeKey), @@ -54,12 +81,9 @@ func PepKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { PortKeeper: &portKeeper, } }, - //func(string) capabilitykeeper.ScopedKeeper { - // return scopeModule - //}, scopedKeeper, - nil, - nil, + accountKeeper, + bankKeeper, nil, nil, ) diff --git a/x/pep/keeper/msg_create_aggregated_key_share_test.go b/x/pep/keeper/msg_create_aggregated_key_share_test.go new file mode 100644 index 00000000..1aa1e928 --- /dev/null +++ b/x/pep/keeper/msg_create_aggregated_key_share_test.go @@ -0,0 +1,142 @@ +package keeper_test + +import ( + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + "github.com/Fairblock/fairyring/testutil/shares" + types2 "github.com/Fairblock/fairyring/x/common/types" + "math/rand" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestAggregatedKeyShareMsgServerCreate(t *testing.T) { + k, ctx := keepertest.PepKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + startParams := types.DefaultParams() + startParams.IsSourceChain = true + + err := k.SetParams(wctx, startParams) + require.NoError(t, err) + + trustedAddr := sample.AccAddress() + + out, err := random.GeneratePubKeyAndShares(1) + require.NoError(t, err) + + derived, err := shares.DeriveShare(out.GeneratedShare[0].Share, 1, "999") + require.NoError(t, err) + + incorrectDerived, err := shares.DeriveShare(out.GeneratedShare[0].Share, 1, "9999") + require.NoError(t, err) + + for _, tc := range []struct { + desc string + request *types.MsgCreateAggregatedKeyShare + response *types.MsgCreateAggregatedKeyShareResponse + err error + errMsg string + }{ + { + desc: "IsSourceChainTriesToCreateAggrKey", + request: &types.MsgCreateAggregatedKeyShare{ + Creator: sample.AccAddress(), + Height: rand.Uint64(), + Data: random.RandHex(192), + }, + errMsg: "submission of external aggregated keyshare not permitted on source chain", + }, + { + desc: "SubmittedFromNotTrustedAddr", + request: &types.MsgCreateAggregatedKeyShare{ + Creator: sample.AccAddress(), + Height: rand.Uint64(), + Data: random.RandHex(192), + }, + errMsg: "msg not from trusted source", + }, + { + desc: "ActiveKeyNotFound", + request: &types.MsgCreateAggregatedKeyShare{ + Creator: trustedAddr, + Height: rand.Uint64(), + Data: random.RandHex(192), + }, + errMsg: "active key not found", + }, + { + desc: "InvalidAggregatedKeyShare", + request: &types.MsgCreateAggregatedKeyShare{ + Creator: trustedAddr, + Height: rand.Uint64(), + Data: random.RandHex(12), + }, + errMsg: "input string length must be equal to 96 bytes", + }, + { + desc: "DecryptError", + request: &types.MsgCreateAggregatedKeyShare{ + Creator: trustedAddr, + Height: 999, + Data: incorrectDerived, + }, + errMsg: "age decrypt: errNoMatch", + }, + { + desc: "ValidAggregatedKeyShare", + request: &types.MsgCreateAggregatedKeyShare{ + Creator: trustedAddr, + Height: 999, + Data: derived, + }, + response: &types.MsgCreateAggregatedKeyShareResponse{}, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := srv.CreateAggregatedKeyShare(wctx, tc.request) + if len(tc.errMsg) > 0 { + require.Equal(t, + nullify.Fill(err.Error()), + nullify.Fill(tc.errMsg)) + } else if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + + if tc.desc == "IsSourceChainTriesToCreateAggrKey" { + startParams.IsSourceChain = false + err = k.SetParams(wctx, startParams) + require.NoError(t, err) + } else if tc.desc == "SubmittedFromNotTrustedAddr" { + param := k.GetParams(wctx) + param.TrustedAddresses = []string{trustedAddr} + err = k.SetParams(wctx, param) + require.NoError(t, err) + } else if tc.desc == "ActiveKeyNotFound" { + k.SetActivePubKey(wctx, types2.ActivePublicKey{ + PublicKey: out.MasterPublicKey, + Creator: trustedAddr, + Expiry: 12342423432, + }) + } + }) + } +} diff --git a/x/pep/keeper/msg_submit_encrypted_tx.go b/x/pep/keeper/msg_submit_encrypted_tx.go index 0a953993..d848528a 100644 --- a/x/pep/keeper/msg_submit_encrypted_tx.go +++ b/x/pep/keeper/msg_submit_encrypted_tx.go @@ -72,16 +72,18 @@ func (k msgServer) SubmitEncryptedTx(goCtx context.Context, msg *types.MsgSubmit minGas := k.MinGasPrice(ctx) - err = k.bankKeeper.SendCoinsFromAccountToModule( - ctx, - senderAddr, - types.ModuleName, - sdk.NewCoins(minGas), - ) + if !minGas.Amount.IsZero() { + err = k.bankKeeper.SendCoinsFromAccountToModule( + ctx, + senderAddr, + types.ModuleName, + sdk.NewCoins(minGas), + ) - if err != nil { - k.Logger().Info(fmt.Sprintf("Error on sending coins: %v", err.Error())) - return nil, err + if err != nil { + k.Logger().Info(fmt.Sprintf("Error on sending coins: %v", err.Error())) + return nil, err + } } encryptedTx := types.EncryptedTx{ diff --git a/x/pep/keeper/msg_submit_encrypted_tx_test.go b/x/pep/keeper/msg_submit_encrypted_tx_test.go new file mode 100644 index 00000000..47b86b53 --- /dev/null +++ b/x/pep/keeper/msg_submit_encrypted_tx_test.go @@ -0,0 +1,120 @@ +package keeper_test + +import ( + "cosmossdk.io/math" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + types2 "github.com/Fairblock/fairyring/x/common/types" + "math/rand" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestSubmitEncryptedTx(t *testing.T) { + k, ctx := keepertest.PepKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + startParams := types.DefaultParams() + startParams.IsSourceChain = true + coin := sdk.NewCoin("stake", math.NewInt(0)) + startParams.MinGasPrice = &coin + + err := k.SetParams(wctx, startParams) + require.NoError(t, err) + + trustedAddr := sample.AccAddress() + + out, err := random.GeneratePubKeyAndShares(1) + require.NoError(t, err) + + for _, tc := range []struct { + desc string + request *types.MsgSubmitEncryptedTx + response *types.MsgSubmitEncryptedTxResponse + err error + errMsg string + }{ + { + desc: "InvalidTargetBlockHeightLowerThanLatestHeight", + request: &types.MsgSubmitEncryptedTx{ + Creator: sample.AccAddress(), + TargetBlockHeight: 0, + Data: random.RandHex(192), + }, + err: types.ErrInvalidTargetBlockHeight, + }, + { + desc: "ActivePubKeyNotFound", + request: &types.MsgSubmitEncryptedTx{ + Creator: sample.AccAddress(), + TargetBlockHeight: rand.Uint64(), + Data: random.RandHex(192), + }, + err: types.ErrActivePubKeyNotFound, + }, + { + desc: "InvalidTargetBlockHeightHigherThanPubKey", + request: &types.MsgSubmitEncryptedTx{ + Creator: trustedAddr, + TargetBlockHeight: 325677454353, + Data: random.RandHex(192), + }, + err: types.ErrInvalidTargetBlockHeight, + }, + { + desc: "InvalidMsgCreator", + request: &types.MsgSubmitEncryptedTx{ + Creator: "abcdefghjkoem0-294", + TargetBlockHeight: 123, + Data: random.RandHex(192), + }, + err: types.ErrInvalidMsgCreator, + }, + { + desc: "ValidEncryptedTx", + request: &types.MsgSubmitEncryptedTx{ + Creator: trustedAddr, + TargetBlockHeight: 999, + Data: random.RandHex(192), + }, + response: &types.MsgSubmitEncryptedTxResponse{}, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := srv.SubmitEncryptedTx(wctx, tc.request) + if len(tc.errMsg) > 0 { + require.Equal(t, + nullify.Fill(err.Error()), + nullify.Fill(tc.errMsg)) + } else if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + + if tc.desc == "ActivePubKeyNotFound" { + k.SetActivePubKey(wctx, types2.ActivePublicKey{ + PublicKey: out.MasterPublicKey, + Creator: trustedAddr, + Expiry: 325677, + }) + } + }) + } +} diff --git a/x/pep/keeper/msg_submit_gen_enc_tx.go b/x/pep/keeper/msg_submit_gen_enc_tx.go index 90045afc..18ea6f89 100644 --- a/x/pep/keeper/msg_submit_gen_enc_tx.go +++ b/x/pep/keeper/msg_submit_gen_enc_tx.go @@ -34,16 +34,18 @@ func (k msgServer) SubmitGeneralEncryptedTx(goCtx context.Context, msg *types.Ms minGas := k.MinGasPrice(ctx) - err = k.bankKeeper.SendCoinsFromAccountToModule( - ctx, - senderAddr, - types.ModuleName, - sdk.NewCoins(minGas), - ) + if !minGas.Amount.IsZero() { + err = k.bankKeeper.SendCoinsFromAccountToModule( + ctx, + senderAddr, + types.ModuleName, + sdk.NewCoins(minGas), + ) - if err != nil { - k.Logger().Info(fmt.Sprintf("Error on sending coins: %v", err.Error())) - return nil, err + if err != nil { + k.Logger().Info(fmt.Sprintf("Error on sending coins: %v", err.Error())) + return nil, err + } } encryptedTx := types.GeneralEncryptedTx{ diff --git a/x/pep/keeper/msg_submit_gen_enc_tx_test.go b/x/pep/keeper/msg_submit_gen_enc_tx_test.go new file mode 100644 index 00000000..85b0c68c --- /dev/null +++ b/x/pep/keeper/msg_submit_gen_enc_tx_test.go @@ -0,0 +1,102 @@ +package keeper_test + +import ( + "cosmossdk.io/math" + "github.com/Fairblock/fairyring/testutil/nullify" + "github.com/Fairblock/fairyring/testutil/random" + "github.com/Fairblock/fairyring/testutil/sample" + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestSubmitGeneralEncryptedTx(t *testing.T) { + k, ctx := keepertest.PepKeeper(t) + srv := keeper.NewMsgServerImpl(k) + wctx := sdk.UnwrapSDKContext(ctx) + + startParams := types.DefaultParams() + startParams.IsSourceChain = true + coin := sdk.NewCoin("stake", math.NewInt(0)) + startParams.MinGasPrice = &coin + + err := k.SetParams(wctx, startParams) + require.NoError(t, err) + + trustedAddr := sample.AccAddress() + + validIdentity := random.RandHex(16) + + for _, tc := range []struct { + desc string + request *types.MsgSubmitGeneralEncryptedTx + response *types.MsgSubmitEncryptedTxResponse + err error + errMsg string + }{ + { + desc: "InvalidIdentity", + request: &types.MsgSubmitGeneralEncryptedTx{ + Creator: sample.AccAddress(), + ReqId: random.RandHex(32), + Data: random.RandHex(192), + }, + err: types.ErrInvalidIdentity, + }, + { + desc: "InvalidMsgCreator", + request: &types.MsgSubmitGeneralEncryptedTx{ + Creator: "abcdefghjkoem0-294", + ReqId: validIdentity, + Data: random.RandHex(192), + }, + err: types.ErrInvalidMsgCreator, + }, + { + desc: "ValidEncryptedTx", + request: &types.MsgSubmitGeneralEncryptedTx{ + Creator: trustedAddr, + ReqId: validIdentity, + Data: random.RandHex(192), + }, + response: &types.MsgSubmitEncryptedTxResponse{}, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := srv.SubmitGeneralEncryptedTx(wctx, tc.request) + if len(tc.errMsg) > 0 { + require.Equal(t, + nullify.Fill(err.Error()), + nullify.Fill(tc.errMsg)) + } else if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + + if tc.desc == "InvalidIdentity" { + k.SetEntry(wctx, types.GenEncTxExecutionQueue{ + Creator: sample.AccAddress(), + RequestId: validIdentity, + Identity: validIdentity, + Pubkey: random.RandHex(96), + TxList: nil, + AggrKeyshare: random.RandHex(96), + }) + } + }) + } +} From 864d98f2a600a4d9a554a863504ac4599fde467b Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Tue, 8 Oct 2024 09:39:23 -0400 Subject: [PATCH 31/41] Add contract calback tests to chain upgrade test script --- scripts/tests/TestChainUpgrade.sh | 220 ++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) diff --git a/scripts/tests/TestChainUpgrade.sh b/scripts/tests/TestChainUpgrade.sh index c15f98f2..319ffbf3 100755 --- a/scripts/tests/TestChainUpgrade.sh +++ b/scripts/tests/TestChainUpgrade.sh @@ -263,6 +263,8 @@ echo $(pwd) echo $CURRENT_PATH $CURRENT_PATH/scripts/tests/keyshareSender.sh $BINARY $CHAIN_HOME tcp://localhost:26657 $VALIDATOR_1 $CHAINID_1 > $WORKING_DIR/keyshareSender.log 2>&1 & +CONTRACT_DIR=$CURRENT_PATH/scripts/tests/fairyring_contract + echo "Query submitted key share on chain $CHAINID_1" RESULT=$($BINARY query keyshare list-key-share -o json) RESULT_SENDER=$(echo "$RESULT" | jq -r '.keyShare[0].validator') @@ -451,3 +453,221 @@ if [[ "$TARGET_BAL_AFTER" == "$TARGET_BAL" ]]; then echo "ERROR: Pep module encrypted tx execution error. Expected Target Balance to be updated, got same balance: '$TARGET_BAL_AFTER $TARGET_BAL_DENOM'" exit 1 fi + + +echo "############################" +echo "# Testing Private KeyShare #" +echo "############################" + +SCEP_PUBKEY1="A/MdHVpitzHNSdD1Zw3kY+L5PEIPyd9l6sD5i4aIfXp9" +SCEP_PUBKEY2="Ak9iJuH5l5/XdmS6U+ojbutXnGzBnQf++HVOfKanVEc+" + +SCEP_PRIV_KEY1="a267fb03b3e6dc381550ea0257ace31433698f16248ba111dfb75550364d31fe" +SCEP_PRIV_KEY2="ef1450bdc18396f2254f52d8c525c0d933a8f146ec2a681eaf319f5899f2f60d" + +echo "Creating new Private Request in pep module on chain $CHAIN_ID" +RESULT=$($BINARY tx pep request-private-keyshare test_req_1 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT + +sleep $(($BLOCK_TIME * 2)) + +echo "Query private keyshare request on chain $CHAIN_ID" +SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $WALLET_1/test_req_1 --node tcp://localhost:26657 -o json) +echo $SHOW_PRIVATE_REQ +REQ_ID=$(echo $SHOW_PRIVATE_REQ | jq -r '.req_id') +echo "Identity for private keyshare request 1 is: $REQ_ID" + +sleep $(($BLOCK_TIME * 2)) + +echo "Requesting for private keyshares on Source chain" +RESULT=$($BINARY tx pep get-private-keyshare $REQ_ID $SCEP_PUBKEY1 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT + +sleep $(($BLOCK_TIME * 2)) + +EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $REQ_ID) +EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') + +ENC_KS=$($BINARY secp-encrypter -p "$SCEP_PUBKEY1" -k "$EXTRACTED_SHARE") + +# echo $ENC_KS + +while true; do + echo "Submitting Private Key Share" + + RESULT=$($BINARY tx keyshare submit-encrypted-keyshare $REQ_ID $WALLET_1 $ENC_KS 1 --from $VALIDATOR_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test -o json -y) + echo "$RESULT" + check_tx_err $RESULT + if [[ $? -eq 0 ]]; then + break + fi +done + +sleep $(($BLOCK_TIME * 2)) + +echo "Query private keyshare request on chain $CHAIN_ID" +SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $WALLET_1/test_req_1 --node tcp://localhost:26657 -o json) +ENC_KEYSHARES=$(echo "$SHOW_PRIVATE_REQ" | jq -r '.encrypted_keyshares') + +if [ "$ENC_KEYSHARES" = "[]" ]; then + echo "encrypted_keyshares is empty." + exit 1 +fi + +echo $SHOW_PRIVATE_REQ + +echo "Sending get private keyshare request without previous entry" +REQ_ID="test_req_dummy_1" +RESULT=$($BINARY tx pep get-private-keyshare $REQ_ID $SCEP_PUBKEY1 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT + +sleep $(($BLOCK_TIME * 2)) + +echo "Query private keyshare request on chain $CHAIN_ID" +SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $REQ_ID --node tcp://localhost:26657 -o json) +echo $SHOW_PRIVATE_REQ + +EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $REQ_ID) +EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') + +ENC_KS=$($BINARY secp-encrypter -p "$SCEP_PUBKEY1" -k "$EXTRACTED_SHARE") + +while true; do + echo "Submitting Private Key Share" + + RESULT=$($BINARY tx keyshare submit-encrypted-keyshare $REQ_ID $WALLET_1 $ENC_KS 1 --from $VALIDATOR_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test -o json -y) + echo "$RESULT" + check_tx_err $RESULT + if [[ $? -eq 0 ]]; then + break + fi +done + +sleep $(($BLOCK_TIME * 2)) + +echo "Query private keyshare request on chain $CHAIN_ID" +SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $REQ_ID --node tcp://localhost:26657 -o json) +ENC_KEYSHARES=$(echo "$SHOW_PRIVATE_REQ" | jq -r '.encrypted_keyshares') + +if [ "$ENC_KEYSHARES" = "[]" ]; then + echo "encrypted_keyshares is empty." + exit 1 +fi + +echo $SHOW_PRIVATE_REQ + +echo "############################" +echo "# Testing Decryption Query #" +echo "############################" + +echo "Query general keyshare request on chain $CHAIN_ID" +LIST_KEYSHARE_REQ=$($BINARY query pep list-keyshare-req --node tcp://localhost:26657 -o json) +IDENTITY=$(echo $LIST_KEYSHARE_REQ | jq -r '.keyshares[0].identity') +AGGR_KEYSHARE=$(echo $LIST_KEYSHARE_REQ | jq -r '.keyshares[0].aggr_keyshare') +echo "Identity for keyshare request is: $IDENTITY" +echo "Aggregated keyshare for request is: $AGGR_KEYSHARE" + +echo "Encrypting data with Pub key: '$PUB_KEY'" +TEST_DATA="test_data_1" +CIPHER=$($BINARY encrypt $IDENTITY $PUB_KEY $TEST_DATA --node tcp://localhost:26657) + +echo "Encrypted Data: '$CIPHER'" + +echo "Attempting decryption of data via pep query" +RSP=$($BINARY query pep decrypt-data $PUB_KEY $AGGR_KEYSHARE $CIPHER --node tcp://localhost:26657 -o json) +DECRYPTED_DATA=$(echo $RSP | jq -r '.decrypted_data') + +if [[ "$TEST_DATA" == "$DECRYPTED_DATA" ]]; then + echo "Data successfully decrypted" +else + echo "Data decryption unsuccessful. Expected: '$TEST_DATA' ; found: '$DECRYPTED_DATA'" + echo "Response from decryption query: '$RSP'" + exit 1 +fi + +echo "#############################################" +echo "# Testing contract callback on source chain #" +echo "#############################################" + +cd $CONTRACT_DIR + +echo "Compiling contract" +cargo build --release --target wasm32-unknown-unknown + +echo "Optimizing Contract" +docker run --rm -v "$(pwd)":/code \ + --mount type=volume,source="$(basename "$(pwd)")_cache",target=/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + cosmwasm/optimizer:0.16.0 + +echo "Deploying smart contract on source chain" +RESULT=$($BINARY tx wasm store $CONTRACT_DIR/artifacts/fairyring_contract.wasm --from $WALLET_1 --gas 9000000 --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test --fees 9000000ufairy -o json -y) +check_tx_code $RESULT +RESULT=$(wait_for_tx $RESULT) +echo $RESULT + +sleep 10 + +echo "Instantiating the contract" +RESULT=$($BINARY tx wasm instantiate 1 '{"identity": "init_identity", "pubkey": "init_pubkey", "aggr_keyshare": "init_keyshare"}' --admin $WALLET_1 --from $WALLET_1 --gas 9000000 --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test --fees 9000000ufairy --label test_contract_1 -o json -y) +check_tx_code $RESULT + +sleep 10 + +echo "Creating new General keyshare Request on chain fairyring_test_1" +RESULT=$($BINARY tx pep request-general-keyshare 30s contract123 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT + +sleep 10 + +REQ_ID="$WAL1_ADDR/contract123" +CONTRACT_ADDR="fairy14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9stsyf7v" + + +echo "Registering contract with identity" +RESULT=$($BINARY tx pep register-contract $CONTRACT_ADDR $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT +RESULT=$(wait_for_tx_source $RESULT) + +sleep 10 + +echo "Request Generation of Aggr keyshare" +RESULT=$($BINARY tx pep get-general-keyshare $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test -o json -y) +echo "$RESULT" +check_tx_code $RESULT + +sleep 6 + +EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $REQ_ID) +EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') + +while true; do + echo "Submitting General Key Share" + + RESULT=$($BINARY tx keyshare create-general-key-share "private-gov-identity" $REQ_ID $EXTRACTED_SHARE 1 --from $VALIDATOR_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_HOME --chain-id $CHAINID_1 --node tcp://localhost:26657 --broadcast-mode sync --keyring-backend test -o json -y) + echo "$RESULT" + check_tx_err $RESULT + if [ $? -eq 0 ]; then + break + fi +done + +sleep 15 + +echo "Query Contract state" +RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"get_stored_data":{"identity": "'"$REQ_ID"'"}}' --node tcp://localhost:26657 -o json) +echo $RSP + +echo "#########################################################" +echo "# Testing decryption from contract request source chain #" +echo "#########################################################" + +echo "Testing with pubkey provided explicitly" +RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"decrypt_data": {"pubkey": "a2a4472488440341db3252447af1c31e06fd32d7067e300ed60052fcdd131fd702bf901e1dd0122a312bb582a9a375a3", "aggr_keyshare": "a3b49bbffd655aa37e0b71a4d90862e1f70bdd0aab48587307ef74c2b3e12fd2ea42d88fc5f592e5caf83d33d7f93454196f32137817ceb5ecb41fbe48c3734bb11510febd6988302dd2c362deb3479b4946daa399fb149e63c0a5c45b48292d", "encrypted_data": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20646973744942450a686e4a7641376d5655797679397166465230447849417464374c3152586371484542687736306a316f325a446e567453626a4759374a4d2f5a524752654e536b0a574d6f56567966674d55546f363944502f4f624a6544424e6f47694b50746a6b316a523075464276536372326d766948543238524f6e473755647835683077510a6c734767656554424336786e7834626e496d737874410a2d2d2d20793668724135506e5233563568414a35646f732b574e325932334b72742b383946306d4d743138595a59490a43129dfd9ddbb210374314a96ab1b06260b4e1abf7d3fac77029043c8bdbe0a6efd2b73f95f75be0"}}' --node tcp://localhost:26657 -o json) +echo $RSP + +echo "Testing with pubkey not provided" +RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"decrypt_data": {"pubkey": "", "aggr_keyshare": "a3b49bbffd655aa37e0b71a4d90862e1f70bdd0aab48587307ef74c2b3e12fd2ea42d88fc5f592e5caf83d33d7f93454196f32137817ceb5ecb41fbe48c3734bb11510febd6988302dd2c362deb3479b4946daa399fb149e63c0a5c45b48292d", "encrypted_data": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20646973744942450a686e4a7641376d5655797679397166465230447849417464374c3152586371484542687736306a316f325a446e567453626a4759374a4d2f5a524752654e536b0a574d6f56567966674d55546f363944502f4f624a6544424e6f47694b50746a6b316a523075464276536372326d766948543238524f6e473755647835683077510a6c734767656554424336786e7834626e496d737874410a2d2d2d20793668724135506e5233563568414a35646f732b574e325932334b72742b383946306d4d743138595a59490a43129dfd9ddbb210374314a96ab1b06260b4e1abf7d3fac77029043c8bdbe0a6efd2b73f95f75be0"}}' --node tcp://localhost:26657 -o json) +echo $RSP + +echo "Run 'pkill fairyringd' to stop fairyring" \ No newline at end of file From 59c98f633c9eb7d4a2e22c2217746ff61ba5394a Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Tue, 8 Oct 2024 10:06:55 -0400 Subject: [PATCH 32/41] Update to check chain height instead of latest height on src chain --- scripts/tests/keyshare.sh | 2 +- scripts/tests/pep.sh | 16 ++++++++-------- testutil/keeper/keyshare.go | 2 ++ x/pep/keeper/msg_submit_encrypted_tx.go | 13 +++++++++---- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/scripts/tests/keyshare.sh b/scripts/tests/keyshare.sh index cb379aac..10f845cc 100755 --- a/scripts/tests/keyshare.sh +++ b/scripts/tests/keyshare.sh @@ -184,7 +184,7 @@ fi CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_DIR/$CHAINID_1 --node tcp://localhost:16657 -o json | jq -r '.block.header.height') -TARGET_HEIGHT=$((CURRENT_BLOCK+1)) +TARGET_HEIGHT=$((CURRENT_BLOCK+2)) EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $TARGET_HEIGHT) EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') diff --git a/scripts/tests/pep.sh b/scripts/tests/pep.sh index 84d484fe..1f37aaa9 100755 --- a/scripts/tests/pep.sh +++ b/scripts/tests/pep.sh @@ -164,10 +164,10 @@ CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_DIR/$CH RESULT=$($BINARY query keyshare list-aggregated-key-share --node $CHAIN1_NODE -o json) AGG_KEY_HEIGHT=$(echo "$RESULT" | jq -r '.aggregatedKeyShare | last | .height') AGG_KEY=$(echo "$RESULT" | jq -r '.aggregatedKeyShare | last | .data') -if [ "$CURRENT_BLOCK" -gt "$AGG_KEY_HEIGHT" ]; then - echo "ERROR: Height of the aggregated key from key share module '$AGG_KEY_HEIGHT' is less than current block height '$CURRENT_BLOCK'" - exit 1 -fi +#if [ "$CURRENT_BLOCK" -gt "$AGG_KEY_HEIGHT" ]; then +# echo "ERROR: Height of the aggregated key from key share module '$AGG_KEY_HEIGHT' is less than current block height '$CURRENT_BLOCK'" +# exit 1 +#fi CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_DIR/$CHAINID_2 --node $CHAIN2_NODE -o json | jq -r '.block.header.height') echo "Chain 2 Current Block: $CURRENT_BLOCK" @@ -188,10 +188,10 @@ CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_DIR/$CH RESULT=$($BINARY query keyshare list-aggregated-key-share --node $CHAIN1_NODE -o json) AGG_KEY_HEIGHT=$(echo "$RESULT" | jq -r '.aggregatedKeyShare | last | .height') AGG_KEY=$(echo "$RESULT" | jq -r '.aggregatedKeyShare | last | .data') -if [ "$CURRENT_BLOCK" -gt "$AGG_KEY_HEIGHT" ]; then - echo "ERROR: Height of the aggregated key from key share module '$AGG_KEY_HEIGHT' is less than current block height '$CURRENT_BLOCK'" - exit 1 -fi +#if [ "$CURRENT_BLOCK" -gt "$AGG_KEY_HEIGHT" ]; then +# echo "ERROR: Height of the aggregated key from key share module '$AGG_KEY_HEIGHT' is less than current block height '$CURRENT_BLOCK'" +# exit 1 +#fi echo "Encrypting signed tx with Pub key: '$PUB_KEY'" diff --git a/testutil/keeper/keyshare.go b/testutil/keeper/keyshare.go index 7624f2c6..216f9839 100644 --- a/testutil/keeper/keyshare.go +++ b/testutil/keeper/keyshare.go @@ -87,6 +87,8 @@ func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context, pepkeeper.Keeper, pepScopedKeeper, accountKeeper, nil, + nil, + nil, ) stakingKeeper := stakingkeeper.NewKeeper( diff --git a/x/pep/keeper/msg_submit_encrypted_tx.go b/x/pep/keeper/msg_submit_encrypted_tx.go index 0a953993..b7fb1e3d 100644 --- a/x/pep/keeper/msg_submit_encrypted_tx.go +++ b/x/pep/keeper/msg_submit_encrypted_tx.go @@ -13,12 +13,17 @@ import ( func (k msgServer) SubmitEncryptedTx(goCtx context.Context, msg *types.MsgSubmitEncryptedTx) (*types.MsgSubmitEncryptedTxResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + params := k.GetParams(ctx) - strHeight := k.GetLatestHeight(ctx) - height, err := strconv.ParseUint(strHeight, 10, 64) + height := uint64(ctx.BlockHeight()) - if err != nil { - height = uint64(ctx.BlockHeight()) + if !params.IsSourceChain { + strHeight := k.GetLatestHeight(ctx) + latestHeight, err := strconv.ParseUint(strHeight, 10, 64) + + if err == nil { + height = latestHeight + } } if msg.TargetBlockHeight <= height { From 94a7c3cfc8179f8455ee079d0c3d3e9265429228 Mon Sep 17 00:00:00 2001 From: p0p3ye Date: Tue, 8 Oct 2024 10:07:40 -0400 Subject: [PATCH 33/41] Remove error when aggr key exists on submitting general keyshare --- x/keyshare/keeper/msg_create_general_key_share.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/x/keyshare/keeper/msg_create_general_key_share.go b/x/keyshare/keeper/msg_create_general_key_share.go index a720b4a9..0f1652bc 100644 --- a/x/keyshare/keeper/msg_create_general_key_share.go +++ b/x/keyshare/keeper/msg_create_general_key_share.go @@ -67,7 +67,16 @@ func (k msgServer) CreateGeneralKeyShare(goCtx context.Context, msg *types.MsgCr return nil, types.ErrKeyShareRequestNotFound.Wrapf(", got id value: %s", msg.IdValue) } if keyShareReq.AggrKeyshare != "" { - return nil, types.ErrAggKeyAlreadyExists.Wrapf(", identity: %s, Aggregated key: %s", msg.IdValue, keyShareReq.AggrKeyshare) + return &types.MsgCreateGeneralKeyShareResponse{ + Creator: msg.Creator, + IdType: msg.IdType, + IdValue: msg.IdValue, + KeyShare: msg.KeyShare, + KeyShareIndex: msg.KeyShareIndex, + ReceivedBlockHeight: uint64(ctx.BlockHeight()), + Success: true, + }, nil + // return nil, types.ErrAggKeyAlreadyExists.Wrapf(", identity: %s, Aggregated key: %s", msg.IdValue, keyShareReq.AggrKeyshare) } } From edd61e6ddf77f6aa6f5dc3b6bee8b9f92d8dc7f8 Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Wed, 9 Oct 2024 13:59:46 +0530 Subject: [PATCH 34/41] adding unit tests for msgs --- app/wasm.go | 30 ----- go.mod | 4 +- testutil/keeper/pep.go | 15 ++- unsigned.json | 1 + unsigned2.json | 1 + .../keeper/msg_get_general_key_share_test.go | 107 +++++++++++++++ x/pep/keeper/msg_get_private_keyshares.go | 3 +- .../keeper/msg_get_private_keyshares_test.go | 116 ++++++++++++++++ x/pep/keeper/msg_register_contract.go | 5 + x/pep/keeper/msg_register_contract_test.go | 37 ++++++ .../msg_request_general_key_share_test.go | 114 ++++++++++++++++ .../msg_request_private_identity_test.go | 125 ++++++++++++++++++ x/pep/keeper/msg_unregister_contract.go | 5 + x/pep/keeper/msg_unregister_contract_test.go | 37 ++++++ 14 files changed, 565 insertions(+), 35 deletions(-) create mode 100644 unsigned.json create mode 100644 unsigned2.json create mode 100644 x/pep/keeper/msg_get_general_key_share_test.go create mode 100644 x/pep/keeper/msg_get_private_keyshares_test.go create mode 100644 x/pep/keeper/msg_register_contract_test.go create mode 100644 x/pep/keeper/msg_request_general_key_share_test.go create mode 100644 x/pep/keeper/msg_request_private_identity_test.go create mode 100644 x/pep/keeper/msg_unregister_contract_test.go diff --git a/app/wasm.go b/app/wasm.go index cbc2620c..c7ba7804 100644 --- a/app/wasm.go +++ b/app/wasm.go @@ -97,10 +97,6 @@ func (app *App) registerWasmModules( return nil, err } - // if err := app.setAnteHandler(app.txConfig, wasmConfig, app.GetKey(wasmtypes.StoreKey)); err != nil { - // return nil, err - // } - if manager := app.SnapshotManager(); manager != nil { err := manager.RegisterExtensions( wasmkeeper.NewWasmSnapshotter(app.CommitMultiStore(), &app.WasmKeeper), @@ -144,29 +140,3 @@ func (app *App) setPostHandler() error { app.SetPostHandler(postHandler) return nil } - -// func (app *App) setAnteHandler(txConfig client.TxConfig, wasmConfig wasmtypes.WasmConfig, txCounterStoreKey *storetypes.KVStoreKey) error { -// anteHandler, err := NewAnteHandler( -// HandlerOptions{ -// HandlerOptions: ante.HandlerOptions{ -// AccountKeeper: app.AccountKeeper, -// BankKeeper: app.BankKeeper, -// SignModeHandler: txConfig.SignModeHandler(), -// FeegrantKeeper: app.FeeGrantKeeper, -// SigGasConsumer: ante.DefaultSigVerificationGasConsumer, -// }, -// IBCKeeper: app.IBCKeeper, -// WasmConfig: &wasmConfig, -// WasmKeeper: &app.WasmKeeper, -// TXCounterStoreService: runtime.NewKVStoreService(txCounterStoreKey), -// CircuitKeeper: &app.CircuitBreakerKeeper, -// }, -// ) -// if err != nil { -// return fmt.Errorf("failed to create AnteHandler: %s", err) -// } - -// // Set the AnteHandler for the app -// app.SetAnteHandler(anteHandler) -// return nil -// } diff --git a/go.mod b/go.mod index 864af620..6f5aa205 100644 --- a/go.mod +++ b/go.mod @@ -62,6 +62,8 @@ require ( google.golang.org/protobuf v1.34.1 ) +require github.com/stretchr/objx v0.5.2 // indirect + require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 // indirect cloud.google.com/go v0.112.0 // indirect @@ -103,7 +105,7 @@ require ( github.com/cometbft/cometbft-db v0.9.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.1.4 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect diff --git a/testutil/keeper/pep.go b/testutil/keeper/pep.go index 91397b40..436c9c40 100644 --- a/testutil/keeper/pep.go +++ b/testutil/keeper/pep.go @@ -1,11 +1,12 @@ package keeper import ( + "testing" + "github.com/cosmos/cosmos-sdk/codec/address" keeper2 "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" - "testing" "cosmossdk.io/log" "cosmossdk.io/store" @@ -44,11 +45,17 @@ func PepKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { stateStore.MountStoreWithDB(authStoreKey, storetypes.StoreTypeIAVL, db) require.NoError(t, stateStore.LoadLatestVersion()) + ctx := sdk.NewContext(stateStore, cmtproto.Header{}, false, log.NewNopLogger()) + registry := codectypes.NewInterfaceRegistry() appCodec := codec.NewProtoCodec(registry) capabilityKeeper := capabilitykeeper.NewKeeper(appCodec, storeKey, memStoreKey) authority := authtypes.NewModuleAddress(govtypes.ModuleName) + // Register module account and other types + authtypes.RegisterInterfaces(registry) + types.RegisterInterfaces(registry) + scopedKeeper := capabilityKeeper.ScopeToModule(ibcexported.ModuleName) portKeeper := portkeeper.NewKeeper(scopedKeeper) // scopeModule := capabilityKeeper.ScopeToModule(types.ModuleName) @@ -63,6 +70,10 @@ func PepKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { authority.String(), ) + // Create the module account for the 'pep' module + moduleAcc := authtypes.NewEmptyModuleAccount(types.ModuleName, authtypes.Minter, authtypes.Burner) + accountKeeper.SetModuleAccount(ctx, moduleAcc) + bankKeeper := bankkeeper.NewBaseKeeper( appCodec, runtime.NewKVStoreService(bankStoreKey), accountKeeper, @@ -88,8 +99,6 @@ func PepKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { nil, ) - ctx := sdk.NewContext(stateStore, cmtproto.Header{}, false, log.NewNopLogger()) - // Initialize params if err := k.SetParams(ctx, types.DefaultParams()); err != nil { panic(err) diff --git a/unsigned.json b/unsigned.json new file mode 100644 index 00000000..6181cb0d --- /dev/null +++ b/unsigned.json @@ -0,0 +1 @@ +{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"fairy1qnk2n4nlkpw9xfqntladh74w6ujtulwnsgww3g","to_address":"fairy10h9stc5v6ntgeygf5xf945njqq5h32r5lxfsqr","amount":[{"denom":"stake","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[{"denom":"ufairy","amount":"200000"}],"gas_limit":"200000","payer":"","granter":""},"tip":null},"signatures":[]} diff --git a/unsigned2.json b/unsigned2.json new file mode 100644 index 00000000..871f6994 --- /dev/null +++ b/unsigned2.json @@ -0,0 +1 @@ +{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"fairy1qnk2n4nlkpw9xfqntladh74w6ujtulwnsgww3g","to_address":"fairy10h9stc5v6ntgeygf5xf945njqq5h32r5lxfsqr","amount":[{"denom":"stake","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""},"tip":null},"signatures":[]} diff --git a/x/pep/keeper/msg_get_general_key_share_test.go b/x/pep/keeper/msg_get_general_key_share_test.go new file mode 100644 index 00000000..5a4f56a4 --- /dev/null +++ b/x/pep/keeper/msg_get_general_key_share_test.go @@ -0,0 +1,107 @@ +package keeper_test + +import ( + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + kstypes "github.com/Fairblock/fairyring/x/keyshare/types" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + "github.com/stretchr/testify/require" +) + +func TestGetGeneralKeyshare(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + goCtx := sdk.WrapSDKContext(ctx) + srv := keeper.NewMsgServerImpl(k) + + creator := "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq" + + // Test case when entry is not found + msg := &types.MsgGetGeneralKeyshare{ + Creator: creator, + ReqId: "invalid_req_id", + } + + _, err := srv.GetGeneralKeyshare(goCtx, msg) + require.Error(t, err) + require.Equal(t, "request not found", err.Error()) + + // Test case when creator is unauthorized + entry := types.GenEncTxExecutionQueue{ + Creator: "authorized_creator", + RequestId: "test_req_id", + Identity: "test_identity", + } + + k.SetEntry(ctx, entry) + + msg = &types.MsgGetGeneralKeyshare{ + Creator: "unauthorized_creator", + ReqId: "test_req_id", + } + + _, err = srv.GetGeneralKeyshare(goCtx, msg) + require.Error(t, err) + require.Equal(t, "unauthorized request. only creator can make this request", err.Error()) + + // Test case when IsSourceChain is true + k.SetParams(ctx, types.Params{IsSourceChain: true}) + + msg = &types.MsgGetGeneralKeyshare{ + Creator: "authorized_creator", + ReqId: "test_req_id", + } + + _, err = srv.GetGeneralKeyshare(goCtx, msg) + require.NoError(t, err) + + // Ensure the correct request is stored + req, found := k.GetSignalQueueEntry(ctx, "test_req_id") + require.True(t, found) + require.NotNil(t, req) + require.Equal(t, "test_identity", req.Identity) +} + +func TestOnAcknowledgementGetAggrKeysharePacket(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + + packet := channeltypes.Packet{} + packetData := kstypes.GetAggrKeysharePacketData{ + Identity: "test_identity", + } + ack := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Result{ + Result: []byte(`{}`), + }, + } + + // Test success case for OnAcknowledgementGetAggrKeysharePacket + err := k.OnAcknowledgementGetAggrKeysharePacket(ctx, packet, packetData, ack) + require.NoError(t, err) + + // Test error case for unmarshalling acknowledgment + invalidAck := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Result{ + Result: []byte("invalid_json"), + }, + } + + err = k.OnAcknowledgementGetAggrKeysharePacket(ctx, packet, packetData, invalidAck) + require.Error(t, err) + require.Equal(t, "cannot unmarshal acknowledgment", err.Error()) + + // Test when Acknowledgement_Error is returned + errorAck := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Error{ + Error: "test_error", + }, + } + + err = k.OnAcknowledgementGetAggrKeysharePacket(ctx, packet, packetData, errorAck) + require.NoError(t, err) +} diff --git a/x/pep/keeper/msg_get_private_keyshares.go b/x/pep/keeper/msg_get_private_keyshares.go index 1dd0fc3c..8544164a 100644 --- a/x/pep/keeper/msg_get_private_keyshares.go +++ b/x/pep/keeper/msg_get_private_keyshares.go @@ -7,6 +7,7 @@ import ( "time" sdkerrors "cosmossdk.io/errors" + "cosmossdk.io/math" commontypes "github.com/Fairblock/fairyring/x/common/types" kstypes "github.com/Fairblock/fairyring/x/keyshare/types" "github.com/Fairblock/fairyring/x/pep/types" @@ -37,7 +38,7 @@ func (k msgServer) GetPrivateKeyshares(goCtx context.Context, msg *types.MsgGetP params := k.GetParams(ctx) - if params.PrivateKeysharePrice.IsPositive() { + if params.PrivateKeysharePrice.Amount.GT(math.ZeroInt()) { err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, requester, types.ModuleName, diff --git a/x/pep/keeper/msg_get_private_keyshares_test.go b/x/pep/keeper/msg_get_private_keyshares_test.go new file mode 100644 index 00000000..5eeed1fc --- /dev/null +++ b/x/pep/keeper/msg_get_private_keyshares_test.go @@ -0,0 +1,116 @@ +package keeper_test + +import ( + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + commontypes "github.com/Fairblock/fairyring/x/common/types" + kstypes "github.com/Fairblock/fairyring/x/keyshare/types" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestGetPrivateKeyshares(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + goCtx := sdk.WrapSDKContext(ctx) + srv := keeper.NewMsgServerImpl(k) + + creator := "cosmos1nm0rrq86ucezaf8uj35pq9fpwr5r82cl8sc7p5" + requester := sdk.AccAddress(creator) + + price := sdk.NewInt64Coin("ufairy", 0) + params := types.Params{ + PrivateKeysharePrice: &price, + IsSourceChain: true, + } + k.SetParams(ctx, params) + + // Test case when entry and pubkey are not found + msg := &types.MsgGetPrivateKeyshares{ + Creator: creator, + ReqId: "test_req_id_1", + SecpPubkey: "test_pubkey", + } + + _, err := srv.GetPrivateKeyshares(goCtx, msg) + require.Error(t, err) + require.Equal(t, "entry and pubkey not found", err.Error()) + + // Set a mock active pubkey and test the entry creation + k.SetActivePubKey(ctx, commontypes.ActivePublicKey{ + PublicKey: "mock_pubkey", + }) + + _, err = srv.GetPrivateKeyshares(goCtx, msg) + require.NoError(t, err) + + // Ensure the private request is stored + entry, found := k.GetPrivateRequest(ctx, "test_req_id_1") + require.True(t, found) + require.Equal(t, "test_req_id_1", entry.ReqId) + + // Mock the bank keeper for the SendCoinsFromAccountToModule call + mockBankKeeper := new(MockBankKeeper) + mockBankKeeper.On("SendCoinsFromAccountToModule", ctx, requester, types.ModuleName, sdk.NewCoins(*params.PrivateKeysharePrice)). + Return(nil).Once() + + _, err = srv.GetPrivateKeyshares(goCtx, msg) + require.NoError(t, err) +} + +func TestOnAcknowledgementGetPrivateKeysharePacket(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + + packet := channeltypes.Packet{} + packetData := kstypes.GetPrivateKeysharePacketData{ + Identity: "test_identity", + Requester: "test_creator", + SecpPubkey: "test_pubkey", + } + ack := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Result{ + Result: []byte(`{}`), + }, + } + + // Test success case for OnAcknowledgementGetPrivateKeysharePacket + err := k.OnAcknowledgementGetPrivateKeysharePacket(ctx, packet, packetData, ack) + require.NoError(t, err) + + // Test error case for unmarshalling acknowledgment + invalidAck := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Result{ + Result: []byte("invalid_json"), + }, + } + + err = k.OnAcknowledgementGetPrivateKeysharePacket(ctx, packet, packetData, invalidAck) + require.Error(t, err) + require.Equal(t, "cannot unmarshal acknowledgment", err.Error()) + + // Test when Acknowledgement_Error is returned + errorAck := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Error{ + Error: "test_error", + }, + } + + err = k.OnAcknowledgementGetPrivateKeysharePacket(ctx, packet, packetData, errorAck) + require.NoError(t, err) +} + +// MockBankKeeper is a mock implementation of the bank keeper for testing purposes +type MockBankKeeper struct { + mock.Mock +} + +func (m *MockBankKeeper) SendCoinsFromAccountToModule(ctx sdk.Context, fromAddr sdk.AccAddress, moduleName string, amt sdk.Coins) error { + args := m.Called(ctx, fromAddr, moduleName, amt) + return args.Error(0) +} diff --git a/x/pep/keeper/msg_register_contract.go b/x/pep/keeper/msg_register_contract.go index 0b0ae2a6..862a66b9 100644 --- a/x/pep/keeper/msg_register_contract.go +++ b/x/pep/keeper/msg_register_contract.go @@ -3,6 +3,7 @@ package keeper import ( "context" "errors" + "reflect" "github.com/Fairblock/fairyring/x/pep/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -19,6 +20,10 @@ func (k msgServer) RegisterContract( return nil, errors.New("invalid contract address") } + if k.wasmKeeper == nil || reflect.ValueOf(k.wasmKeeper).IsZero() { + return nil, errors.New("wasm keeper has not been set") + } + contractInfo := k.wasmKeeper.GetContractInfo(ctx, contracAddr) if contractInfo == nil { return nil, errors.New("contract information not found") diff --git a/x/pep/keeper/msg_register_contract_test.go b/x/pep/keeper/msg_register_contract_test.go new file mode 100644 index 00000000..84d3748c --- /dev/null +++ b/x/pep/keeper/msg_register_contract_test.go @@ -0,0 +1,37 @@ +package keeper_test + +import ( + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestRegisterContract(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + goCtx := sdk.WrapSDKContext(ctx) + srv := keeper.NewMsgServerImpl(k) + + creator := "cosmos1nm0rrq86ucezaf8uj35pq9fpwr5r82cl8sc7p5" + + // Test case 1: Invalid contract address + msg := &types.MsgRegisterContract{ + Creator: creator, + ContractAddress: "invalid_address", // Invalid Bech32 address + Identity: "test_identity", + } + + _, err := srv.RegisterContract(goCtx, msg) + require.Error(t, err) + require.Equal(t, "invalid contract address", err.Error()) + + // Test case 2: Contract information not found + msg.ContractAddress = creator + _, err = srv.RegisterContract(goCtx, msg) + require.Error(t, err) + require.Equal(t, "wasm keeper has not been set", err.Error()) +} diff --git a/x/pep/keeper/msg_request_general_key_share_test.go b/x/pep/keeper/msg_request_general_key_share_test.go new file mode 100644 index 00000000..086969a5 --- /dev/null +++ b/x/pep/keeper/msg_request_general_key_share_test.go @@ -0,0 +1,114 @@ +package keeper_test + +import ( + "errors" + "testing" + "time" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + kstypes "github.com/Fairblock/fairyring/x/keyshare/types" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + "github.com/stretchr/testify/require" +) + +func TestRequestGeneralKeyshare(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + goCtx := sdk.WrapSDKContext(ctx) + srv := keeper.NewMsgServerImpl(k) + + creator := "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq" + duration := time.Duration(5 * time.Second) + // Test case when ReqId already exists + reqID := types.RequestId{ + Creator: creator, + ReqId: "test_req_id_1", + } + k.SetRequestId(ctx, reqID) + + msg := &types.MsgRequestGeneralKeyshare{ + Creator: creator, + ReqId: "test_req_id_1", + EstimatedDelay: &duration, + } + + _, err := srv.RequestGeneralKeyshare(goCtx, msg) + require.Error(t, err) + require.Equal(t, types.ErrReqIDAlreadyExists, err) + + // Test case when EstimatedDelay is nil + msg.EstimatedDelay = nil + msg.ReqId = "test_req_id_2" + + _, err = srv.RequestGeneralKeyshare(goCtx, msg) + require.Error(t, err) + require.Equal(t, errors.New("could not parse estimated delay"), err) + + // Test case when IsSourceChain is true + k.SetParams(ctx, types.Params{IsSourceChain: true}) + + msg.EstimatedDelay = &duration + msg.ReqId = "test_req_id_3" + + resp, err := srv.RequestGeneralKeyshare(goCtx, msg) + require.NoError(t, err) + require.NotNil(t, resp) + require.Equal(t, "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/test_req_id_3", resp.ReqId) +} + +func TestOnAcknowledgementRequestAggrKeysharePacket(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + + packet := channeltypes.Packet{} + packetData := kstypes.RequestAggrKeysharePacketData{ + Requester: "test_creator", + Id: &kstypes.RequestAggrKeysharePacketData_RequestId{ + RequestId: "test_request_id", + }, + } + ack := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Result{ + Result: []byte(`{"identity":"test_identity", "pubkey":"test_pubkey"}`), + }, + } + + // Test success case for OnAcknowledgementRequestAggrKeysharePacket + err := k.OnAcknowledgementRequestAggrKeysharePacket(ctx, packet, packetData, ack) + require.NoError(t, err) + + // Ensure entry is created + entry, found := k.GetEntry(ctx, "test_request_id") + require.True(t, found) + require.Equal(t, "test_identity", entry.Identity) + require.Equal(t, "test_pubkey", entry.Pubkey) + + // Test when entry already exists + err = k.OnAcknowledgementRequestAggrKeysharePacket(ctx, packet, packetData, ack) + require.Error(t, err) + require.Equal(t, "entry already exists", err.Error()) + + // Test error case for unmarshalling acknowledgment + invalidAck := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Result{ + Result: []byte("invalid_json"), + }, + } + + err = k.OnAcknowledgementRequestAggrKeysharePacket(ctx, packet, packetData, invalidAck) + require.Error(t, err) + require.Equal(t, "cannot unmarshal acknowledgment", err.Error()) + + // Test when Acknowledgement_Error is returned + errorAck := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Error{ + Error: "test_error", + }, + } + + err = k.OnAcknowledgementRequestAggrKeysharePacket(ctx, packet, packetData, errorAck) + require.NoError(t, err) +} diff --git a/x/pep/keeper/msg_request_private_identity_test.go b/x/pep/keeper/msg_request_private_identity_test.go new file mode 100644 index 00000000..bd924b7d --- /dev/null +++ b/x/pep/keeper/msg_request_private_identity_test.go @@ -0,0 +1,125 @@ +package keeper_test + +import ( + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + commontypes "github.com/Fairblock/fairyring/x/common/types" + kstypes "github.com/Fairblock/fairyring/x/keyshare/types" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + "github.com/stretchr/testify/require" +) + +func TestRequestPrivateIdentity(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + goCtx := sdk.WrapSDKContext(ctx) + srv := keeper.NewMsgServerImpl(k) + + creator := "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq" + + // Test case when ReqId already exists + reqID := types.RequestId{ + Creator: creator, + ReqId: "test_req_id_1", + } + k.SetRequestId(ctx, reqID) + + msg := &types.MsgRequestPrivateIdentity{ + Creator: creator, + ReqId: "test_req_id_1", + } + + _, err := srv.RequestPrivateIdentity(goCtx, msg) + require.Error(t, err) + require.Equal(t, types.ErrReqIDAlreadyExists, err) + + // Test case when IsSourceChain is true + k.SetParams(ctx, types.Params{IsSourceChain: true}) + + msg = &types.MsgRequestPrivateIdentity{ + Creator: creator, + ReqId: "test_req_id_2", + } + + resp, err := srv.RequestPrivateIdentity(goCtx, msg) + require.NoError(t, err) + require.NotNil(t, resp) + require.Equal(t, "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/test_req_id_2", resp.ReqId) + + // Ensure the private request is stored + req, found := k.GetPrivateRequest(ctx, "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/test_req_id_2") + require.True(t, found) + require.Equal(t, "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/test_req_id_2", req.ReqId) +} + +func TestOnAcknowledgementRequestPrivateKeysharePacket(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + + creator := "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq" + + packet := channeltypes.Packet{} + packetData := kstypes.RequestPrivateKeysharePacketData{ + Requester: creator, + RequestId: "test_request_id_1", + } + ack := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Result{ + Result: []byte(`{"pubkey":"test_pubkey"}`), + }, + } + + // Test case when ReqId already exists + privReq := types.PrivateRequest{ + Creator: creator, + ReqId: "test_request_id_1", + Pubkey: "", + EncryptedKeyshares: make([]*commontypes.EncryptedKeyshare, 0), + } + + k.SetPrivateRequest(ctx, privReq) + + // Test success case for OnAcknowledgementRequestPrivateKeysharePacket + err := k.OnAcknowledgementRequestPrivateKeysharePacket(ctx, packet, packetData, ack) + require.NoError(t, err) + + // Ensure the private request is updated + entry, found := k.GetPrivateRequest(ctx, "test_request_id_1") + require.True(t, found) + require.Equal(t, "test_pubkey", entry.Pubkey) + + // Test case when entry does not exist + invalidPacketData := kstypes.RequestPrivateKeysharePacketData{ + Requester: creator, + RequestId: "invalid_request_id", + } + + err = k.OnAcknowledgementRequestPrivateKeysharePacket(ctx, packet, invalidPacketData, ack) + require.Error(t, err) + require.Equal(t, "entry does not exists", err.Error()) + + // Test error case for unmarshalling acknowledgment + invalidAck := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Result{ + Result: []byte("invalid_json"), + }, + } + + err = k.OnAcknowledgementRequestPrivateKeysharePacket(ctx, packet, packetData, invalidAck) + require.Error(t, err) + require.Equal(t, "cannot unmarshal acknowledgment", err.Error()) + + // Test when Acknowledgement_Error is returned + errorAck := channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Error{ + Error: "test_error", + }, + } + + err = k.OnAcknowledgementRequestPrivateKeysharePacket(ctx, packet, packetData, errorAck) + require.NoError(t, err) +} diff --git a/x/pep/keeper/msg_unregister_contract.go b/x/pep/keeper/msg_unregister_contract.go index 9d36f242..0bff7f5f 100644 --- a/x/pep/keeper/msg_unregister_contract.go +++ b/x/pep/keeper/msg_unregister_contract.go @@ -3,6 +3,7 @@ package keeper import ( "context" "errors" + "reflect" "github.com/Fairblock/fairyring/x/pep/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -19,6 +20,10 @@ func (k msgServer) UnregisterContract( return nil, errors.New("invalid contract address") } + if k.wasmKeeper == nil || reflect.ValueOf(k.wasmKeeper).IsZero() { + return nil, errors.New("wasm keeper has not been set") + } + contractInfo := k.wasmKeeper.GetContractInfo(ctx, contracAddr) if contractInfo == nil { return nil, errors.New("contract information not found") diff --git a/x/pep/keeper/msg_unregister_contract_test.go b/x/pep/keeper/msg_unregister_contract_test.go new file mode 100644 index 00000000..70ded2ab --- /dev/null +++ b/x/pep/keeper/msg_unregister_contract_test.go @@ -0,0 +1,37 @@ +package keeper_test + +import ( + "testing" + + keepertest "github.com/Fairblock/fairyring/testutil/keeper" + "github.com/Fairblock/fairyring/x/pep/keeper" + "github.com/Fairblock/fairyring/x/pep/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestUnregisterContract(t *testing.T) { + // Initialize the keeper, context, and other dependencies + k, ctx := keepertest.PepKeeper(t) + goCtx := sdk.WrapSDKContext(ctx) + srv := keeper.NewMsgServerImpl(k) + + creator := "cosmos1nm0rrq86ucezaf8uj35pq9fpwr5r82cl8sc7p5" + + // Test case 1: Invalid contract address + msg := &types.MsgUnregisterContract{ + Creator: creator, + ContractAddress: "invalid_address", // Invalid Bech32 address + Identity: "test_identity", + } + + _, err := srv.UnregisterContract(goCtx, msg) + require.Error(t, err) + require.Equal(t, "invalid contract address", err.Error()) + + // Test case 2: Contract information not found + msg.ContractAddress = creator + _, err = srv.UnregisterContract(goCtx, msg) + require.Error(t, err) + require.Equal(t, "wasm keeper has not been set", err.Error()) +} From 45837c84ea6a961df927eaa224f8ae5e06688fa6 Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Wed, 9 Oct 2024 14:29:05 +0530 Subject: [PATCH 35/41] adding contract callback for blockwise id --- x/pep/module/module.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/x/pep/module/module.go b/x/pep/module/module.go index a40f9265..f309da10 100644 --- a/x/pep/module/module.go +++ b/x/pep/module/module.go @@ -251,6 +251,23 @@ func (am AppModule) BeginBlock(cctx context.Context) error { } else { am.keeper.Logger().Info(fmt.Sprintf("No encrypted tx found at block %d", h)) } + + // execute registered contracts + contracts, found := am.keeper.GetContractEntriesByID(ctx, strconv.FormatUint(h, 10)) + if found && len(contracts.Contracts) != 0 { + for _, contract := range contracts.Contracts { + am.keeper.ExecuteContract( + ctx, + contract.ContractAddress, + types.ExecuteContractMsg{ + Identity: strconv.FormatUint(h, 10), + Pubkey: activePubkey.PublicKey, + AggrKeyshare: key.Data, + }, + ) + } + } + continue } From 5dcf893398967b97fa5e7569b8ec913f059290c1 Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Wed, 9 Oct 2024 10:02:40 -0400 Subject: [PATCH 36/41] Remove unsigned.json --- unsigned.json | 1 - unsigned2.json | 1 - 2 files changed, 2 deletions(-) delete mode 100644 unsigned.json delete mode 100644 unsigned2.json diff --git a/unsigned.json b/unsigned.json deleted file mode 100644 index 6181cb0d..00000000 --- a/unsigned.json +++ /dev/null @@ -1 +0,0 @@ -{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"fairy1qnk2n4nlkpw9xfqntladh74w6ujtulwnsgww3g","to_address":"fairy10h9stc5v6ntgeygf5xf945njqq5h32r5lxfsqr","amount":[{"denom":"stake","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[{"denom":"ufairy","amount":"200000"}],"gas_limit":"200000","payer":"","granter":""},"tip":null},"signatures":[]} diff --git a/unsigned2.json b/unsigned2.json deleted file mode 100644 index 871f6994..00000000 --- a/unsigned2.json +++ /dev/null @@ -1 +0,0 @@ -{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"fairy1qnk2n4nlkpw9xfqntladh74w6ujtulwnsgww3g","to_address":"fairy10h9stc5v6ntgeygf5xf945njqq5h32r5lxfsqr","amount":[{"denom":"stake","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""},"tip":null},"signatures":[]} From 2a389fd0e4bcb73733d937daf6f95acb28f810f3 Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Wed, 9 Oct 2024 10:05:58 -0400 Subject: [PATCH 37/41] Fix test keyshare keeper error --- testutil/keeper/keyshare.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/testutil/keeper/keyshare.go b/testutil/keeper/keyshare.go index 85dde216..f384c632 100644 --- a/testutil/keeper/keyshare.go +++ b/testutil/keeper/keyshare.go @@ -104,8 +104,6 @@ func KeyshareKeeper(t testing.TB) (keeper.Keeper, sdk.Context, pepkeeper.Keeper, bankKeeper, nil, nil, - nil, - nil, ) stakingKeeper := stakingkeeper.NewKeeper( From 685576a470c413e27a886d66007be5d1e5cf3bc5 Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Wed, 9 Oct 2024 10:57:31 -0400 Subject: [PATCH 38/41] Update deps version --- go.mod | 71 ++++++++++++++-------------- go.sum | 145 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 111 insertions(+), 105 deletions(-) diff --git a/go.mod b/go.mod index 6f5aa205..ffb1cba7 100644 --- a/go.mod +++ b/go.mod @@ -33,11 +33,11 @@ require ( github.com/FairBlock/DistributedIBE v0.0.0-20231211202607-d457df6869db github.com/btcsuite/btcd v0.22.3 github.com/bufbuild/buf v1.30.0 - github.com/cometbft/cometbft v0.38.9 + github.com/cometbft/cometbft v0.38.12 github.com/cosmos/cosmos-db v1.0.2 github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/cosmos-sdk v0.50.6 - github.com/cosmos/gogoproto v1.5.0 + github.com/cosmos/gogoproto v1.7.0 github.com/cosmos/ibc-go/modules/capability v1.0.0 github.com/cosmos/ibc-go/v8 v8.2.1 github.com/cosmos/interchain-security/v3 v3.2.0-consumer-rc0.0.20231123140529-1819e73f6197 @@ -51,25 +51,29 @@ require ( github.com/hashicorp/go-metrics v0.5.3 github.com/skip-mev/block-sdk/v2 v2.1.5 github.com/spf13/cast v1.6.0 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.18.2 + github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 golang.org/x/tools v0.22.0 google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 google.golang.org/grpc v1.65.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 - google.golang.org/protobuf v1.34.1 + google.golang.org/protobuf v1.34.2 ) -require github.com/stretchr/objx v0.5.2 // indirect +require ( + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/stretchr/objx v0.5.2 // indirect +) require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240221180331-f05a6f4403ce.1 // indirect - cloud.google.com/go v0.112.0 // indirect + cloud.google.com/go v0.112.1 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/iam v1.1.6 // indirect - cloud.google.com/go/storage v1.36.0 // indirect + cloud.google.com/go/storage v1.38.0 // indirect connectrpc.com/connect v1.15.0 // indirect connectrpc.com/otelconnect v0.7.0 // indirect cosmossdk.io/collections v0.4.0 // indirect @@ -78,7 +82,7 @@ require ( github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/CosmWasm/wasmvm/v2 v2.0.0 // indirect + github.com/CosmWasm/wasmvm/v2 v2.0.3 // indirect github.com/DataDog/datadog-go v3.2.0+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect @@ -88,7 +92,7 @@ require ( github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.2 + github.com/btcsuite/btcd/btcec/v2 v2.3.4 github.com/bufbuild/protocompile v0.9.0 // indirect github.com/bufbuild/protovalidate-go v0.6.0 // indirect github.com/bufbuild/protoyaml-go v0.1.8 // indirect @@ -97,12 +101,12 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect - github.com/cockroachdb/errors v1.11.1 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v1.1.0 // indirect + github.com/cockroachdb/pebble v1.1.1 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft-db v0.9.1 // indirect + github.com/cometbft/cometbft-db v0.11.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/go-bip39 v1.0.0 @@ -110,7 +114,7 @@ require ( github.com/cosmos/iavl v1.1.4 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/creachadair/atomicfile v0.3.2 // indirect github.com/creachadair/tomledit v0.0.25 // indirect github.com/danieljoos/wincred v1.2.1 // indirect @@ -124,7 +128,7 @@ require ( github.com/distribution/reference v0.5.0 // indirect github.com/docker/cli v25.0.4+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v25.0.4+incompatible // indirect + github.com/docker/docker v25.0.6+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.1 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -161,13 +165,13 @@ require ( github.com/google/s2a-go v0.1.7 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/googleapis/gax-go/v2 v2.12.3 // indirect github.com/gorilla/handlers v1.5.2 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.4 // indirect + github.com/hashicorp/go-getter v1.7.5 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-plugin v1.5.2 // indirect @@ -186,12 +190,11 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/kilic/bls12-381 v0.1.0 // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/linxGnu/grocksdb v1.8.14 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/manifoldco/promptui v0.9.0 // indirect @@ -214,13 +217,13 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pkg/profile v1.7.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_golang v1.20.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.52.2 // indirect - github.com/prometheus/procfs v0.13.0 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/cors v1.10.1 // indirect + github.com/rs/cors v1.11.1 // indirect github.com/rs/zerolog v1.32.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -238,9 +241,9 @@ require ( github.com/vbatts/tar-split v0.11.5 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect - go.etcd.io/bbolt v1.3.8 // indirect + go.etcd.io/bbolt v1.3.10 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.27.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect @@ -251,17 +254,17 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.26.0 // indirect golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect golang.org/x/mod v0.18.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/oauth2 v0.20.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/term v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.5.0 // indirect - google.golang.org/api v0.162.0 // indirect + google.golang.org/api v0.171.0 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 80218a83..ec1def1d 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9 cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= -cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= +cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= +cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= @@ -171,8 +171,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8= -cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= +cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= @@ -231,8 +231,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25 github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CosmWasm/wasmvm/v2 v2.0.0 h1:IqNCI2G0mvs7K6ej17/I28805rVqnu+Y1cWDqIdwb08= -github.com/CosmWasm/wasmvm/v2 v2.0.0/go.mod h1:su9lg5qLr7adV95eOfzjZWkGiky8WNaNIHDr7Fpu7Ck= +github.com/CosmWasm/wasmvm/v2 v2.0.3 h1:G9jpwDk+qFUfDkXCigpWPn9JTGM0H7egKzWQnMEONwE= +github.com/CosmWasm/wasmvm/v2 v2.0.3/go.mod h1:su9lg5qLr7adV95eOfzjZWkGiky8WNaNIHDr7Fpu7Ck= github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= @@ -294,10 +294,10 @@ github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5M github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd v0.22.3 h1:kYNaWFvOw6xvqP0vR20RP1Zq1DVMBxEO8QN5d1/EfNg= github.com/btcsuite/btcd v0.22.3/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= -github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= -github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/buf v1.30.0 h1:V/Gir+aVKukqI/w2Eqoiv4tqUs01KBWP9t3Hz/9/25I= @@ -346,28 +346,28 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= 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/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= -github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4= -github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E= +github.com/cockroachdb/pebble v1.1.1 h1:XnKU22oiCLy2Xn8vp1re67cXg4SAasg/WDt1NtcRFaw= +github.com/cockroachdb/pebble v1.1.1/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.9 h1:cJBJBG0mPKz+sqelCi/hlfZjadZQGdDNnu6YQ1ZsUHQ= -github.com/cometbft/cometbft v0.38.9/go.mod h1:xOoGZrtUT+A5izWfHSJgl0gYZUE7lu7Z2XIS1vWG/QQ= -github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= -github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= +github.com/cometbft/cometbft v0.38.12 h1:OWsLZN2KcSSFe8bet9xCn07VwhBnavPea3VyPnNq1bg= +github.com/cometbft/cometbft v0.38.12/go.mod h1:GPHp3/pehPqgX1930HmK1BpBLZPxB75v/dZg8Viwy+o= +github.com/cometbft/cometbft-db v0.11.0 h1:M3Lscmpogx5NTbb1EGyGDaFRdsoLWrUWimFEyf7jej8= +github.com/cometbft/cometbft-db v0.11.0/go.mod h1:GDPJAC/iFHNjmZZPN8V8C1yr/eyityhi2W1hz2MGKSc= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -391,8 +391,8 @@ github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4x github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= -github.com/cosmos/gogoproto v1.5.0 h1:SDVwzEqZDDBoslaeZg+dGE55hdzHfgUA40pEanMh52o= -github.com/cosmos/gogoproto v1.5.0/go.mod h1:iUM31aofn3ymidYG6bUR5ZFrk+Om8p5s754eMUcyp8I= +github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= +github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/cosmos/iavl v1.1.4 h1:Z0cVVjeQqOUp78/nWt/uhQy83vYluWlAMGQ4zbH9G34= github.com/cosmos/iavl v1.1.4/go.mod h1:vCYmRQUJU1wwj0oRD3wMEtOM9sJNDP+GFMaXmIxZ/rU= github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE= @@ -407,8 +407,8 @@ github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5n github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/atomicfile v0.3.2 h1:f8haU8NcZ1NABfhHafpJIG+atR7481lqnx04clrxSOA= github.com/creachadair/atomicfile v0.3.2/go.mod h1:3ZSR9ApQoZLvVNI5eRhzpU0a2Efu88TgNBIm0jRXCgA= github.com/creachadair/tomledit v0.0.25 h1:QBzoVTd4hVsKF4tTrrHFbrtAbxT41WvW348aE4lvr3o= @@ -451,8 +451,8 @@ github.com/docker/cli v25.0.4+incompatible h1:DatRkJ+nrFoYL2HZUzjM5Z5sAmcA5XGp+A github.com/docker/cli v25.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v25.0.4+incompatible h1:XITZTrq+52tZyZxUOtFIahUf3aH367FLxJzt9vZeAF8= -github.com/docker/docker v25.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg= +github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -692,8 +692,8 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -705,8 +705,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -726,8 +726,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.7.4 h1:3yQjWuxICvSpYwqSayAdKRFcvBl1y/vogCxczWSmix0= -github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4= +github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -822,8 +822,8 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -836,14 +836,14 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linxGnu/grocksdb v1.8.14 h1:HTgyYalNwBSG/1qCQUIott44wU5b2Y9Kr3z7SK5OfGQ= @@ -900,6 +900,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -989,8 +991,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.1 h1:IMJXHOD6eARkQpxo8KkhgEVFlBNm+nkrFUyGlIu7Na8= +github.com/prometheus/client_golang v1.20.1/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1005,16 +1007,16 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.52.2 h1:LW8Vk7BccEdONfrJBDffQGRtpSzi5CQaRZGtboOO2ck= -github.com/prometheus/common v0.52.2/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o= -github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -1027,8 +1029,8 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -1071,16 +1073,16 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1141,8 +1143,8 @@ github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWp github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1155,8 +1157,8 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= @@ -1209,8 +1211,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= 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= @@ -1311,8 +1313,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1338,8 +1340,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1354,8 +1356,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1455,13 +1457,13 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1472,8 +1474,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1549,8 +1551,9 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -1600,8 +1603,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.162.0 h1:Vhs54HkaEpkMBdgGdOT2P6F0csGG/vxDS0hWHJzmmps= -google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= +google.golang.org/api v0.171.0 h1:w174hnBPqut76FzW5Qaupt7zY8Kql6fiVjgys4f58sU= +google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAmjC9o= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1785,8 +1788,8 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 7447182a28636a69a1e1801e10b9f62f4c539f2e Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Wed, 9 Oct 2024 10:58:06 -0400 Subject: [PATCH 39/41] Fix pep test script --- scripts/tests/pep.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/tests/pep.sh b/scripts/tests/pep.sh index 1f37aaa9..1b62fac7 100755 --- a/scripts/tests/pep.sh +++ b/scripts/tests/pep.sh @@ -164,10 +164,10 @@ CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_DIR/$CH RESULT=$($BINARY query keyshare list-aggregated-key-share --node $CHAIN1_NODE -o json) AGG_KEY_HEIGHT=$(echo "$RESULT" | jq -r '.aggregatedKeyShare | last | .height') AGG_KEY=$(echo "$RESULT" | jq -r '.aggregatedKeyShare | last | .data') -#if [ "$CURRENT_BLOCK" -gt "$AGG_KEY_HEIGHT" ]; then -# echo "ERROR: Height of the aggregated key from key share module '$AGG_KEY_HEIGHT' is less than current block height '$CURRENT_BLOCK'" -# exit 1 -#fi +if [ "$AGG_KEY_HEIGHT" -gt "$CURRENT_BLOCK" ]; then + echo "ERROR: Height of the aggregated key from key share module '$AGG_KEY_HEIGHT' is greater than current block height '$CURRENT_BLOCK'" + exit 1 +fi CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_DIR/$CHAINID_2 --node $CHAIN2_NODE -o json | jq -r '.block.header.height') echo "Chain 2 Current Block: $CURRENT_BLOCK" @@ -188,10 +188,10 @@ CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_DIR/$CH RESULT=$($BINARY query keyshare list-aggregated-key-share --node $CHAIN1_NODE -o json) AGG_KEY_HEIGHT=$(echo "$RESULT" | jq -r '.aggregatedKeyShare | last | .height') AGG_KEY=$(echo "$RESULT" | jq -r '.aggregatedKeyShare | last | .data') -#if [ "$CURRENT_BLOCK" -gt "$AGG_KEY_HEIGHT" ]; then -# echo "ERROR: Height of the aggregated key from key share module '$AGG_KEY_HEIGHT' is less than current block height '$CURRENT_BLOCK'" -# exit 1 -#fi +if [ "$AGG_KEY_HEIGHT" -gt "$CURRENT_BLOCK" ]; then + echo "ERROR: Height of the aggregated key from key share module '$AGG_KEY_HEIGHT' is greater than current block height '$CURRENT_BLOCK'" + exit 1 +fi echo "Encrypting signed tx with Pub key: '$PUB_KEY'" From 7827d9b0e520df50fdebb110bf1666258055622d Mon Sep 17 00:00:00 2001 From: ap0calypse644 Date: Fri, 11 Oct 2024 02:12:54 +0530 Subject: [PATCH 40/41] adding test for contract callback --- scripts/tests/pep.sh | 20 +++++++++++++++++++- x/pep/module/module.go | 31 +++++++++++++++---------------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/scripts/tests/pep.sh b/scripts/tests/pep.sh index 1b62fac7..11297c45 100755 --- a/scripts/tests/pep.sh +++ b/scripts/tests/pep.sh @@ -911,6 +911,24 @@ echo "Query Contract state" RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"get_stored_data":{"identity": "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/contract123"}}' --node $CHAIN1_NODE -o json) echo $RSP +CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_DIR/$CHAINID_1 --node tcp://localhost:16657 -o json | jq -r '.block.header.height') +TARGET_HEIGHT=$((CURRENT_BLOCK+2)) +EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $TARGET_HEIGHT) +EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') + +echo "Registering contract with blockwise identity $TARGET_HEIGHT" +RESULT=$($BINARY tx pep register-contract $CONTRACT_ADDR $TARGET_HEIGHT --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) +check_tx_code $RESULT +RESULT=$(wait_for_tx_source $RESULT) + +sleep 10 + +echo "waiting for Submitting keyshare" + +echo "Query Contract state" +RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"get_stored_data":{"identity": "'"$TARGET_HEIGHT"'"}}' --node $CHAIN1_NODE -o json) +echo $RSP + echo "#########################################################" echo "# Testing decryption from contract request source chain #" echo "#########################################################" @@ -935,4 +953,4 @@ echo "# Test General Encrypted Txs #" echo "###########################################################" echo "" -./scripts/tests/priv_gov.sh $PUB_KEY $1 \ No newline at end of file +# ./scripts/tests/priv_gov.sh $PUB_KEY $1 \ No newline at end of file diff --git a/x/pep/module/module.go b/x/pep/module/module.go index f309da10..34449ca8 100644 --- a/x/pep/module/module.go +++ b/x/pep/module/module.go @@ -251,24 +251,23 @@ func (am AppModule) BeginBlock(cctx context.Context) error { } else { am.keeper.Logger().Info(fmt.Sprintf("No encrypted tx found at block %d", h)) } + continue + } - // execute registered contracts - contracts, found := am.keeper.GetContractEntriesByID(ctx, strconv.FormatUint(h, 10)) - if found && len(contracts.Contracts) != 0 { - for _, contract := range contracts.Contracts { - am.keeper.ExecuteContract( - ctx, - contract.ContractAddress, - types.ExecuteContractMsg{ - Identity: strconv.FormatUint(h, 10), - Pubkey: activePubkey.PublicKey, - AggrKeyshare: key.Data, - }, - ) - } + // execute registered contracts + contracts, found := am.keeper.GetContractEntriesByID(ctx, strconv.FormatUint(h, 10)) + if found && len(contracts.Contracts) != 0 { + for _, contract := range contracts.Contracts { + am.keeper.ExecuteContract( + ctx, + contract.ContractAddress, + types.ExecuteContractMsg{ + Identity: strconv.FormatUint(h, 10), + Pubkey: activePubkey.PublicKey, + AggrKeyshare: key.Data, + }, + ) } - - continue } skPoint, err := am.keeper.GetSKPoint(key.Data, suite) From 20b19795d3769001e8fc0d3ebd22bfbe9fff32ff Mon Sep 17 00:00:00 2001 From: p0p3yee Date: Fri, 11 Oct 2024 00:21:39 -0400 Subject: [PATCH 41/41] Fix script keyshare sender not working --- scripts/tests/fairyringclient_config.yml | 11 +++++ scripts/tests/keyshare.sh | 13 ++++- scripts/tests/keyshareSender.sh | 53 ++++++++++++++------- scripts/tests/pep.sh | 60 ++++++++++++------------ scripts/tests/priv_gov.sh | 6 +-- scripts/tests/start.sh | 8 +++- 6 files changed, 97 insertions(+), 54 deletions(-) create mode 100644 scripts/tests/fairyringclient_config.yml diff --git a/scripts/tests/fairyringclient_config.yml b/scripts/tests/fairyringclient_config.yml new file mode 100644 index 00000000..1caa20a8 --- /dev/null +++ b/scripts/tests/fairyringclient_config.yml @@ -0,0 +1,11 @@ +fairyringnode: + chainid: fairyring_test_1 + denom: ufairy + grpcport: 9090 + ip: 127.0.0.1 + port: 16657 + protocol: http +invalidsharepausethreshold: 5 +metricsport: 2222 +# Private Key is from start script, Account "val1" +privatekey: 823ad58093b111e3c41369ca67103cba89e136995bdbd8a86c6b7eef9ca38b00 \ No newline at end of file diff --git a/scripts/tests/keyshare.sh b/scripts/tests/keyshare.sh index 10f845cc..2d750ef8 100755 --- a/scripts/tests/keyshare.sh +++ b/scripts/tests/keyshare.sh @@ -15,7 +15,7 @@ echo "" BINARY=fairyringd CHAIN_DIR=$(pwd)/data CHAINID_1=fairyring_test_1 -BLOCK_TIME=6 +BLOCK_TIME=1.5 WALLET_1=$($BINARY keys show wallet1 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_1) VALIDATOR_1=$($BINARY keys show val1 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_1) @@ -232,7 +232,7 @@ fi CURRENT_BLOCK=$($BINARY query consensus comet block-latest --home $CHAIN_DIR/$CHAINID_1 --node tcp://localhost:16657 -o json | jq -r '.block.header.height') -TARGET_HEIGHT=$((CURRENT_BLOCK+1)) +TARGET_HEIGHT=$((CURRENT_BLOCK+2)) EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $TARGET_HEIGHT) EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') @@ -249,6 +249,15 @@ if [ "$AGGRED_SHARE" != $EXTRACTED_SHARE ]; then exit 1 fi +#if [ ! -f "$HOME/.fairyringclient/config.yml" ]; then +# fairyringclient config init +#fi +# +#cp "$HOME/.fairyringclient/config.yml" "$HOME/.fairyringclient/config.yml.backup" +#cp ./scripts/tests/fairyringclient_config.yml "$HOME/.fairyringclient/config.yml" +# +#fairyringclient start > $CHAIN_DIR/fairyringclient.log 2>&1 & + ./scripts/tests/keyshareSender.sh $BINARY $CHAIN_DIR/$CHAINID_1 tcp://localhost:16657 $VALIDATOR_1 $CHAINID_1 > $CHAIN_DIR/keyshareSender.log 2>&1 & echo "Query submitted key share on chain fairyring_test_1" diff --git a/scripts/tests/keyshareSender.sh b/scripts/tests/keyshareSender.sh index 2367d490..66a7c293 100755 --- a/scripts/tests/keyshareSender.sh +++ b/scripts/tests/keyshareSender.sh @@ -6,24 +6,35 @@ NODE=$3 FROM=$4 CHAINID=$5 -BLOCK_TIME=5 +BLOCK_TIME=0.5 check_tx_code () { - local TX_CODE=$(echo "$1" | jq -r '.code') - if [ "$TX_CODE" != 0 ]; then - echo "ERROR: Tx failed with code: $TX_CODE" - exit 1 - fi + local TX_CODE=$(echo "$1" | jq -r '.code' 2>/dev/null) + if [ $? -ne 0 ]; then + echo "0" + elif [ "$TX_CODE" != 0 ]; then + echo "0" + else + echo "1" + fi } wait_for_tx () { - sleep $BLOCK_TIME - local TXHASH=$(echo "$1" | jq -r '.txhash') - RESULT=$($BINARY q tx --type=hash $TXHASH --home $HOME --chain-id $CHAINID --node $NODE -o json) - echo "$RESULT" + while true + do + sleep $BLOCK_TIME + local TXHASH=$(echo "$1" | jq -r '.txhash') + RESULT=$($BINARY q tx --type=hash $TXHASH --home $HOME --chain-id $CHAINID --node $NODE -o json 2>/dev/null) + if [ $? -ne 0 ]; then + continue + else + echo "$RESULT" + break + fi + done } -sleep 5 +sleep 3 RESULT=$(fairyringd q keyshare show-active-pub-key --node $NODE -o json | jq) GENERATED_SHARE=$(echo $RESULT | jq -r '.activePubKey.encryptedKeyShares[0].data') @@ -34,12 +45,20 @@ do EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $TARGET_HEIGHT) EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') RESULT=$($BINARY tx keyshare send-keyshare $EXTRACTED_SHARE 1 $TARGET_HEIGHT --from $FROM --gas-prices 1ufairy --home $HOME --chain-id $CHAINID --node $NODE --broadcast-mode sync --keyring-backend test -o json -y) - check_tx_code $RESULT + OUT=$(check_tx_code $RESULT) + if [ $OUT -eq "0" ]; then + echo "Error checking tx code, skip submitting $TARGET_HEIGHT key share" + continue + fi RESULT=$(wait_for_tx $RESULT) - RESULT_EVENT=$(echo "$RESULT" | jq -r '.logs[0].events[2].type') - if [ "$RESULT_EVENT" != "keyshare-aggregated" ]; then - echo "ERROR: KeyShare module submit invalid key share from registered validator error. Expected the key to be aggregated, got '$RESULT_EVENT'" - echo "ERROR MESSAGE: $(echo "$RESULT" | jq -r '.raw_log')" + RESULT_EVENT=$(echo "$RESULT" | jq -r '.events[9].type' 2>/dev/null) + if [ $? -ne 0 ]; then + continue + else + if [ "$RESULT_EVENT" != "keyshare-aggregated" ]; then + echo "ERROR: KeyShare module submit invalid key share from registered validator error. Expected the key to be aggregated, got '$RESULT_EVENT'" + echo "ERROR MESSAGE: $(echo "$RESULT" | jq -r '.raw_log')" + fi + echo "Submitted keyshare for height: $TARGET_HEIGHT" fi - echo "Submitted keyshare for height: $TARGET_HEIGHT" done \ No newline at end of file diff --git a/scripts/tests/pep.sh b/scripts/tests/pep.sh index 11297c45..52eda8a2 100755 --- a/scripts/tests/pep.sh +++ b/scripts/tests/pep.sh @@ -20,7 +20,7 @@ CHAINID_1=fairyring_test_1 CHAIN1_NODE=tcp://localhost:16657 CHAINID_2=fairyring_test_2 CHAIN2_NODE=tcp://localhost:26657 -BLOCK_TIME=5 +BLOCK_TIME=1.5 WALLET_1=$($BINARY keys show wallet1 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_1) VALIDATOR_1=$($BINARY keys show val1 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_1) @@ -48,16 +48,14 @@ check_tx_err () { } wait_for_tx () { - sleep $BLOCK_TIME - sleep $BLOCK_TIME + sleep 2 local TXHASH=$(echo "$1" | jq -r '.txhash') RESULT=$($BINARY q tx --type=hash $TXHASH --home $CHAIN_DIR/$CHAINID_2 --chain-id $CHAINID_2 --node $CHAIN2_NODE -o json) echo "$RESULT" } wait_for_tx_source () { - sleep $BLOCK_TIME - sleep $BLOCK_TIME + sleep 2 local TXHASH=$(echo "$1" | jq -r '.txhash') RESULT=$($BINARY q tx --type=hash $TXHASH --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE -o json) echo "$RESULT" @@ -358,7 +356,7 @@ echo "Creating new General Enc Request in pep module on chain fairyring_test_1" RESULT=$($BINARY tx pep request-general-keyshare 30s testing123 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) check_tx_code $RESULT -sleep 10 +sleep 5 echo "Query general keyshare request on chain fairyring_test_1" LIST_KEYSHARE_REQ=$($BINARY query pep list-keyshare-req --node $CHAIN1_NODE -o json) @@ -395,14 +393,14 @@ CIPHER2=$($BINARY encrypt $IDENTITY "" $SIGNED_DATA_2 --node $CHAIN1_NODE) rm -r unsigned.json &> /dev/null rm -r unsigned2.json &> /dev/null -sleep 10 +sleep 5 echo "Submit general encrypted tx to pep module on chain fairyring_test_1" RESULT=$($BINARY tx pep submit-general-encrypted-tx $CIPHER $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) echo "$RESULT" check_tx_code $RESULT -sleep 6 +sleep 5 echo "Query Keyshare request and check for encrypted tx" TX=$($BINARY query pep show-keyshare-req $REQ_ID --node $CHAIN1_NODE -o json | jq -r '.keyshare.tx_list.encryptedTx[0].data') @@ -416,14 +414,14 @@ RESULT=$($BINARY tx pep submit-general-encrypted-tx $CIPHER2 $REQ_ID --from $WAL echo "$RESULT" check_tx_code $RESULT -sleep 6 +sleep 5 echo "Request Generation of Aggr keyshare" RESULT=$($BINARY tx pep get-general-keyshare $REQ_ID --from $WALLET_1 --gas-prices 1ufairy --gas 900000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) echo "$RESULT" check_tx_code $RESULT -sleep 6 +sleep 5 EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $IDENTITY) EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') @@ -472,7 +470,7 @@ while true; do echo "Found Identity & Request ID" break fi - sleep 10 + sleep 5 done echo "Query account pep nonce before submitting encrypted tx from pep module on chain $CHAINID_2" @@ -508,14 +506,14 @@ CIPHER2=$($BINARY encrypt "$IDENTITY" "" "$SIGNED_DATA_2" --node $CHAIN2_NODE) rm -r unsigned.json &> /dev/null rm -r unsigned2.json &> /dev/null -sleep 10 +sleep 5 echo "Submit general encrypted tx to pep module on chain $CHAINID_2" RESULT=$($BINARY tx pep submit-general-encrypted-tx $CIPHER $REQ_ID --from $WALLET_2 --gas-prices 1ufairy --gas 900000 --home $CHAIN_DIR/$CHAINID_2 --chain-id $CHAINID_2 --node $CHAIN2_NODE --broadcast-mode sync --keyring-backend test -o json -y) echo "$RESULT" check_tx_code $RESULT -sleep 6 +sleep 5 echo "Query Keyshare request and check for encrypted tx" TX=$($BINARY query pep show-keyshare-req $REQ_ID --node $CHAIN2_NODE -o json | jq -r '.keyshare.tx_list.encryptedTx[0].data') @@ -529,14 +527,14 @@ RESULT=$($BINARY tx pep submit-general-encrypted-tx $CIPHER2 $REQ_ID --from $WAL echo "$RESULT" check_tx_code $RESULT -sleep 6 +sleep 5 echo "Request Generation of Aggr keyshare" RESULT=$($BINARY tx pep get-general-keyshare $REQ_ID --from $WALLET_2 --gas-prices 1ufairy --gas 900000 --home $CHAIN_DIR/$CHAINID_2 --chain-id $CHAINID_2 --node $CHAIN2_NODE --broadcast-mode sync --keyring-backend test -o json -y) echo "$RESULT" check_tx_code $RESULT -sleep 6 +sleep 5 EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $IDENTITY) EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') @@ -583,7 +581,7 @@ echo "Creating new Private Request in pep module on chain fairyring_test_1" RESULT=$($BINARY tx pep request-private-keyshare test_req_1 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) check_tx_code $RESULT -sleep 10 +sleep 5 echo "Query private keyshare request on chain fairyring_test_1" SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $WALLET_1/test_req_1 --node $CHAIN1_NODE -o json) @@ -591,13 +589,13 @@ echo $SHOW_PRIVATE_REQ REQ_ID=$(echo $SHOW_PRIVATE_REQ | jq -r '.req_id') echo "Identity for private keyshare request 1 is: $REQ_ID" -sleep 10 +sleep 5 echo "Requesting for private keyshares on Source chain" RESULT=$($BINARY tx pep get-private-keyshare $REQ_ID $SCEP_PUBKEY1 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) check_tx_code $RESULT -sleep 10 +sleep 5 EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $REQ_ID) EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') @@ -617,7 +615,7 @@ while true; do fi done -sleep 10 +sleep 5 echo "Query private keyshare request on chain fairyring_test_1" SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $WALLET_1/test_req_1 --node $CHAIN1_NODE -o json) @@ -635,7 +633,7 @@ REQ_ID="test_req_dummy_1" RESULT=$($BINARY tx pep get-private-keyshare $REQ_ID $SCEP_PUBKEY1 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) check_tx_code $RESULT -sleep 10 +sleep 5 echo "Query private keyshare request on chain fairyring_test_1" SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $REQ_ID --node $CHAIN1_NODE -o json) @@ -659,7 +657,7 @@ while true; do fi done -sleep 10 +sleep 5 echo "Query private keyshare request on chain fairyring_test_1" SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $REQ_ID --node $CHAIN1_NODE -o json) @@ -680,7 +678,7 @@ echo "Creating new Private Request in pep module on chain fairyring_test_2" RESULT=$($BINARY tx pep request-private-keyshare test_req_2 --from $WALLET_2 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_2 --chain-id $CHAINID_2 --node $CHAIN2_NODE --broadcast-mode sync --keyring-backend test -o json -y) check_tx_code $RESULT -sleep 20 +sleep 8 echo "Query private keyshare request on chain fairyring_test_2" SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $WALLET_2/test_req_2 --node $CHAIN2_NODE -o json) @@ -692,7 +690,7 @@ echo "Requesting for private keyshares on destination chain" RESULT=$($BINARY tx pep get-private-keyshare $REQ_ID $SCEP_PUBKEY2 --from $WALLET_2 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_2 --chain-id $CHAINID_2 --node $CHAIN2_NODE --broadcast-mode sync --keyring-backend test -o json -y) check_tx_code $RESULT -sleep 20 +sleep 8 EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $REQ_ID) EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') @@ -729,7 +727,7 @@ REQ_ID="test_req_dummy_2" RESULT=$($BINARY tx pep get-private-keyshare $REQ_ID $SCEP_PUBKEY2 --from $WALLET_2 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_2 --chain-id $CHAINID_2 --node $CHAIN2_NODE --broadcast-mode sync --keyring-backend test -o json -y) check_tx_code $RESULT -sleep 10 +sleep 5 echo "Query private keyshare request on chain fairyring_test_2" SHOW_PRIVATE_REQ=$($BINARY query pep show-private-keyshare-req $REQ_ID --node $CHAIN2_NODE -o json) @@ -835,19 +833,19 @@ echo "Deploying smart contract on source chain" RESULT=$($BINARY tx wasm store $CONTRACT_DIR/artifacts/fairyring_contract.wasm --from $WALLET_1 --gas 9000000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test --fees 9000000ufairy -o json -y) check_tx_code $RESULT -sleep 10 +sleep 5 echo "Instantiating the contract" RESULT=$($BINARY tx wasm instantiate 1 '{"identity": "init_identity", "pubkey": "init_pubkey", "aggr_keyshare": "init_keyshare"}' --admin $WALLET_1 --from $WALLET_1 --gas 9000000 --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test --fees 9000000ufairy --label test_contract_1 -o json -y) check_tx_code $RESULT -sleep 10 +sleep 5 echo "Creating new General keyshare Request on chain fairyring_test_1" RESULT=$($BINARY tx pep request-general-keyshare 30s contract123 --from $WALLET_1 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) check_tx_code $RESULT -sleep 10 +sleep 5 REQ_ID="fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/contract123" CONTRACT_ADDR="fairy14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9stsyf7v" @@ -870,7 +868,7 @@ RESULT=$($BINARY tx pep register-contract $CONTRACT_ADDR $REQ_ID --from $WALLET_ check_tx_code $RESULT RESULT=$(wait_for_tx_source $RESULT) -sleep 10 +sleep 5 echo "Trying to unregistering contract with unauthorized address" RESULT=$($BINARY tx pep unregister-contract $CONTRACT_ADDR $REQ_ID --from $WALLET_3 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node $CHAIN1_NODE --broadcast-mode sync --keyring-backend test -o json -y) @@ -889,7 +887,7 @@ RESULT=$($BINARY tx pep get-general-keyshare $REQ_ID --from $WALLET_1 --gas-pric echo "$RESULT" check_tx_code $RESULT -sleep 6 +sleep 5 EXTRACTED_RESULT=$($BINARY share-generation derive $GENERATED_SHARE 1 $REQ_ID) EXTRACTED_SHARE=$(echo "$EXTRACTED_RESULT" | jq -r '.KeyShare') @@ -905,7 +903,7 @@ while true; do fi done -sleep 15 +sleep 8 echo "Query Contract state" RSP=$($BINARY q wasm contract-state smart $CONTRACT_ADDR '{"get_stored_data":{"identity": "fairy1m9l358xunhhwds0568za49mzhvuxx9uxdra8sq/contract123"}}' --node $CHAIN1_NODE -o json) @@ -921,7 +919,7 @@ RESULT=$($BINARY tx pep register-contract $CONTRACT_ADDR $TARGET_HEIGHT --from $ check_tx_code $RESULT RESULT=$(wait_for_tx_source $RESULT) -sleep 10 +sleep 5 echo "waiting for Submitting keyshare" diff --git a/scripts/tests/priv_gov.sh b/scripts/tests/priv_gov.sh index dcf8f369..ada9cae3 100755 --- a/scripts/tests/priv_gov.sh +++ b/scripts/tests/priv_gov.sh @@ -17,7 +17,7 @@ GENERATOR=ShareGenerator CHAIN_DIR=$(pwd)/data CHAINID_1=fairyring_test_1 CHAINID_2=fairyring_test_2 -BLOCK_TIME=5 +BLOCK_TIME=1.5 WALLET_3=$($BINARY keys show wallet3 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_1) VAL1=$($BINARY keys show val1 -a --keyring-backend test --home $CHAIN_DIR/$CHAINID_1) @@ -58,7 +58,7 @@ GENERATED_SHARE=$2 echo "Creating a new proposal on source chain" RESULT=$($BINARY tx gov submit-proposal $(pwd)/scripts/tests/draft_proposal.json --from $WALLET_3 --gas-prices 1ufairy --home $CHAIN_DIR/$CHAINID_1 --chain-id $CHAINID_1 --node tcp://localhost:16657 --broadcast-mode sync --keyring-backend test -o json -y) -sleep 5 +sleep $BLOCK_TIME check_tx_code $RESULT RESULT=$(wait_for_tx $RESULT "source") @@ -129,7 +129,7 @@ RESULT=$(wait_for_tx $RESULT "source") sleep 25 echo "Checking Status of proposal on Source chain" -sleep 5 +sleep $BLOCK_TIME PROPOSAL=$(fairyringd q gov proposals --home $CHAIN_DIR/$CHAINID_1 --node tcp://localhost:16657 -o json | jq '.proposals[0]') STATUS=$(echo "$PROPOSAL" | jq -r '.status') diff --git a/scripts/tests/start.sh b/scripts/tests/start.sh index 37606e31..3cc4e094 100755 --- a/scripts/tests/start.sh +++ b/scripts/tests/start.sh @@ -30,7 +30,7 @@ GRPCPORT_2=9092 GRPCWEB_1=9091 GRPCWEB_2=9093 -BLOCK_TIME=5 +BLOCK_TIME=1.5 # Stop if it is already running if pgrep -x "$BINARY" >/dev/null; then @@ -57,6 +57,12 @@ if ! mkdir -p $CHAIN_DIR/$CHAINID_2 2>/dev/null; then echo "Failed to create chain folder. Aborting..." exit 1 fi +# +#if ! command -v fairyringclient 2>&1 >/dev/null +#then +# echo "fairyringclient could not be found. Aborting..." +# exit 1 +#fi echo "Initializing $CHAINID_1 & $CHAINID_2..." $BINARY init test --home $CHAIN_DIR/$CHAINID_1 --chain-id=$CHAINID_1 &> /dev/null