From c9450159ed8ad675e4d0d78345cab4dcb3a8dedc Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 10 Apr 2026 17:36:47 +0300 Subject: [PATCH 01/63] feat: extend vote --- abci/extend_vote.go | 134 ++++++++++++++++++++++++++++++++++++++++++++ abci/helpers.go | 32 +++++++++++ config.yml | 7 +++ 3 files changed, 173 insertions(+) create mode 100644 abci/extend_vote.go create mode 100644 abci/helpers.go diff --git a/abci/extend_vote.go b/abci/extend_vote.go new file mode 100644 index 00000000..04898e10 --- /dev/null +++ b/abci/extend_vote.go @@ -0,0 +1,134 @@ +package vote_ext + +import ( + "math/big" + + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/node101-io/mina-signer-go/constants" + "github.com/node101-io/mina-signer-go/field" + "github.com/node101-io/mina-signer-go/keys" + "github.com/node101-io/mina-signer-go/poseidon" +) + +const ActionsReducedRoot string = "pulsar" + +type validatorInfo struct { + ConsensusAddr []byte + Power int64 +} + +func MockSign(voteExtBody VoteExtensionBody) []byte { + return []byte{} +} + +func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]validatorInfo, error) { + + historicalData, err := h.stakingKeeper.GetHistoricalInfo(ctx, currentBlockHeight) + if err != nil { + return nil, err + } + + validatorSet := historicalData.Valset + + var valInfo []validatorInfo + + for _, validator := range validatorSet { + + consAddr, err := validator.GetConsAddr() + if err != nil { + return nil, err + } + + consPower := validator.ConsensusPower(sdk.DefaultPowerReduction) + + valInfo = append(valInfo, validatorInfo{ + ConsensusAddr: consAddr, + Power: consPower, + }) + } + return valInfo, nil +} + +func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []validatorInfo, poseidonHash *poseidon.Poseidon) (*big.Int, error) { + + input := []*big.Int{big.NewInt(0)} + merkleRoot := poseidonHash.Hash(input) + + for _, validator := range valInfo { + input = []*big.Int{} + + minaPubKeyExists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, validator.ConsensusAddr) + if err != nil { + return nil, err + } + if !minaPubKeyExists { + return nil, err + } + + minaPubKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, validator.ConsensusAddr) + if err != nil { + return nil, err + } + + MinaPublicKey, err := keys.PublicKey{}.FromAddress(string(minaPubKey)) + if err != nil { + return nil, err + } + + input = append(input, MinaPublicKey.X) + if MinaPublicKey.IsOdd { + input = append(input, big.NewInt(1)) + } else { + input = append(input, big.NewInt(0)) + } + power := new(big.Int).SetInt64(validator.Power) + input = append(input, power) + + hashOfAddr := poseidonHash.Hash(input) + + input = []*big.Int{merkleRoot, hashOfAddr} + + merkleRoot = poseidonHash.Hash(input) + } + + return merkleRoot, nil + +} + +func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { + return func(ctx sdk.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) { + if req.GetHeight() < 3 { + return &abci.ResponseExtendVote{VoteExtension: []byte{}}, nil + } + + twoBlocksBefore, err := stakingkeeper.Keeper.GetHistoricalInfo(h.stakingKeeper, ctx, req.GetHeight()-2) + if err != nil { + return &abci.ResponseExtendVote{VoteExtension: []byte{}}, err + } + + nextBlockHeight := req.GetHeight() - 1 + + poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) + + nextValSet, err := h.getValidatorSet(ctx, nextBlockHeight) + if err != nil { + return nil, err + } + nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, nextValSet, poseidonHash) + if err != nil { + return nil, err + } + + body := VoteExtensionBody{ + NextBlockHeight: nextBlockHeight, + CurrentStateRoot: twoBlocksBefore.Header.AppHash, + NextValidatorSetHash: nextValidatorSetHash.Bytes(), + } + + bz := MockSign(body) + + return &abci.ResponseExtendVote{VoteExtension: bz}, nil + } +} diff --git a/abci/helpers.go b/abci/helpers.go new file mode 100644 index 00000000..b9b66e3b --- /dev/null +++ b/abci/helpers.go @@ -0,0 +1,32 @@ +package vote_ext + +import ( + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/node101-io/mina-signer-go/keys" + keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" +) + +type SecondaryKey struct { + SecretKey *keys.PrivateKey + PublicKey *keys.PublicKey +} + +type AbciHandler struct { + secondaryKey SecondaryKey + stakingKeeper stakingkeeper.Keeper + keyregistryKeeper keyregistrykeeper.Keeper +} + +type VoteExtensionBody struct { + NextValidatorSetHash []byte + CurrentStateRoot []byte + NextBlockHeight int64 +} + +func NewVoteExtHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Keeper, keyregistryKeeper keyregistrykeeper.Keeper) *AbciHandler { + return &AbciHandler{ + secondaryKey: secondaryKey, + stakingKeeper: stakingKeeper, + keyregistryKeeper: keyregistryKeeper, + } +} diff --git a/config.yml b/config.yml index 4ac7edc1..afd3dd7e 100644 --- a/config.yml +++ b/config.yml @@ -21,6 +21,9 @@ faucet: validators: - name: alice bonded: 100000000pmina + app: + vote_extension: + priv_key: "OhOfQtGMXqcrbfCRPEe4DjLUNHaOcD3RrWuRPBGO82M=" - name: validator1 bonded: 200000000pmina - name: validator2 @@ -40,3 +43,7 @@ genesis: #- mina_key: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" # Validator consensus public key placeholder: ed25519, zero bytes, 32 bytes. # cosmos_key: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" + consensus: + params: + abci: + vote_extensions_enable_height: "1" From 2b0924f3248cb93598243e19ca04d9f1ca3c9ffa Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 10 Apr 2026 18:37:41 +0300 Subject: [PATCH 02/63] feat: verify vote extension --- abci/extend_vote.go | 4 +++ abci/verify_vote_ext.go | 62 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 abci/verify_vote_ext.go diff --git a/abci/extend_vote.go b/abci/extend_vote.go index 04898e10..c5e04b6b 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -23,6 +23,10 @@ func MockSign(voteExtBody VoteExtensionBody) []byte { return []byte{} } +func MockSignatureVerify(voteExtBody VoteExtensionBody, minaKey []byte, reducedRoot string) bool { + return true +} + func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]validatorInfo, error) { historicalData, err := h.stakingKeeper.GetHistoricalInfo(ctx, currentBlockHeight) diff --git a/abci/verify_vote_ext.go b/abci/verify_vote_ext.go new file mode 100644 index 00000000..18eeb14e --- /dev/null +++ b/abci/verify_vote_ext.go @@ -0,0 +1,62 @@ +package vote_ext + +import ( + "fmt" + + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/node101-io/mina-signer-go/constants" + "github.com/node101-io/mina-signer-go/field" + "github.com/node101-io/mina-signer-go/poseidon" +) + +func (h *AbciHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandler { + return func(ctx sdk.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) { + if req.GetHeight() < 3 { + if len(req.VoteExtension) == 0 { + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil + } + + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, fmt.Errorf("rejected") + } + + cosmosValAddr := req.GetValidatorAddress() + + exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, cosmosValAddr) + if err != nil { + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err + } + if !exists { + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err + } + + poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) + + minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, cosmosValAddr) + if err != nil { + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err + } + + valInfo, err := h.getValidatorSet(ctx, req.Height) + if err != nil { + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err + } + + setRoot, err := h.calculateValidatorSetRoot(ctx, valInfo, poseidonHash) + if err != nil { + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err + } + + sigValidity := MockSignatureVerify(VoteExtensionBody{ + NextValidatorSetHash: setRoot.Bytes(), + CurrentStateRoot: ctx.HeaderInfo().AppHash, + NextBlockHeight: req.Height, + }, minaKey, ActionsReducedRoot) + + if !sigValidity { + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err + } + + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil + } +} From 07c8302a41a5d21505113c34901ab2b72b3092fa Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 13 Apr 2026 18:07:02 +0300 Subject: [PATCH 03/63] feat: prepare proposal handler --- abci/helpers.go | 32 ++++++++++++++++++++++ abci/prepare_proposal.go | 59 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 abci/prepare_proposal.go diff --git a/abci/helpers.go b/abci/helpers.go index b9b66e3b..5edc9a33 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -6,6 +6,10 @@ import ( keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" ) +var VoteExtMarker []byte = []byte("VOTEEXT:") + +const AcceptanceRatio float64 = 0.66 + type SecondaryKey struct { SecretKey *keys.PrivateKey PublicKey *keys.PublicKey @@ -15,6 +19,7 @@ type AbciHandler struct { secondaryKey SecondaryKey stakingKeeper stakingkeeper.Keeper keyregistryKeeper keyregistrykeeper.Keeper + votes map[uint64]map[string][]byte // height -> minaAddress -> extension bytes } type VoteExtensionBody struct { @@ -23,6 +28,11 @@ type VoteExtensionBody struct { NextBlockHeight int64 } +type payload struct { + Height uint64 `json:"height"` + Votes map[string][]byte `json:"votes"` +} + func NewVoteExtHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Keeper, keyregistryKeeper keyregistrykeeper.Keeper) *AbciHandler { return &AbciHandler{ secondaryKey: secondaryKey, @@ -30,3 +40,25 @@ func NewVoteExtHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Ke keyregistryKeeper: keyregistryKeeper, } } + +func (h *AbciHandler) storeVote(height uint64, minaKey string, voteExt []byte) { + + voteMap := h.votes[height] + + voteMap[minaKey] = voteExt + +} + +func (h *AbciHandler) fetchVote(height uint64, minaKey string) []byte { + + voteMap := h.votes[height] + + return voteMap[minaKey] +} + +func (h *AbciHandler) fetchVotes(height uint64) map[string][]byte { + + voteMap := h.votes[height] + + return voteMap +} diff --git a/abci/prepare_proposal.go b/abci/prepare_proposal.go new file mode 100644 index 00000000..925c8a17 --- /dev/null +++ b/abci/prepare_proposal.go @@ -0,0 +1,59 @@ +package vote_ext + +import ( + "encoding/json" + "fmt" + + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (h *AbciHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { + + return func(ctx sdk.Context, req *abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) { + + voteExtsForGivenBlock := make(map[string][]byte) + targetHeight := uint64(req.GetHeight() - 1) + + valInfo, err := h.getValidatorSet(ctx, req.Height) + if err != nil { + return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + } + + for _, val := range valInfo { + + exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, val.ConsensusAddr) + if err != nil { + return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + } + if !exists { + return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + } + minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, val.ConsensusAddr) + if err != nil { + return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + } + voteExtsForGivenBlock[string(val.ConsensusAddr)] = h.fetchVote(targetHeight, string(minaKey)) + } + + if len(voteExtsForGivenBlock) == 0 { + return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + } + + pl := payload{Height: targetHeight, Votes: voteExtsForGivenBlock} + bz, err := json.Marshal(pl) + if err != nil { + return nil, fmt.Errorf("") + } + + // prefix makes it easier to identify the vote extension + extTx := append(VoteExtMarker, bz...) + + // prepend to existing txs + txs := make([][]byte, 0, len(req.Txs)+1) + txs = append(txs, extTx) + txs = append(txs, req.Txs...) + + return &abci.ResponsePrepareProposal{Txs: [][]byte{}}, nil + } +} From d115928d4de0c618673d0194548983b77e622596 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 13 Apr 2026 18:07:12 +0300 Subject: [PATCH 04/63] feat: process proposal handler --- abci/process_proposal.go | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 abci/process_proposal.go diff --git a/abci/process_proposal.go b/abci/process_proposal.go new file mode 100644 index 00000000..9a84c843 --- /dev/null +++ b/abci/process_proposal.go @@ -0,0 +1,69 @@ +package vote_ext + +import ( + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/node101-io/mina-signer-go/constants" + "github.com/node101-io/mina-signer-go/field" + "github.com/node101-io/mina-signer-go/poseidon" +) + +func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { + + return func(ctx sdk.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) { + + // If height is 1, we won't have any votes thus skip the proposal + if req.GetHeight() == 1 { + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil + } + + // vote ext reconstruct + currentState, err := stakingkeeper.Keeper.GetHistoricalInfo(h.stakingKeeper, ctx, req.GetHeight()-2) + if err != nil { + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + } + + valInfo, err := h.getValidatorSet(ctx, req.GetHeight()-1) + if err != nil { + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + } + + poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) + + nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, valInfo, poseidonHash) + if err != nil { + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + } + if nextValidatorSetHash == nil { + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + } + + body := VoteExtensionBody{ + NextBlockHeight: req.GetHeight() - 1, + CurrentStateRoot: currentState.Header.AppHash, + NextValidatorSetHash: nextValidatorSetHash.Bytes(), + } + + var signedStakePower int64 + var currentValidatorStakePower int64 + voteExtMap := h.fetchVotes(uint64(req.GetHeight()) - 2) + + for _, val := range valInfo { + if voteExtMap[string(val.ConsensusAddr)] != nil { + signedStakePower += val.Power + } + currentValidatorStakePower += val.Power + } + + if float64(signedStakePower) < float64(currentValidatorStakePower)*AcceptanceRatio { + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + } + + MockSignatureVerify(body, h.secondaryKey.PublicKey.X.Bytes(), ActionsReducedRoot) + + // Vote extension successfully verified + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil + } + +} From e3dc164ed0b78eb97e9d1a2f1be0da68dc97829e Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 27 Apr 2026 17:29:55 +0300 Subject: [PATCH 05/63] fix: return values fixed and used integer arithmetic instead of float --- abci/prepare_proposal.go | 21 ++++++++++----------- abci/process_proposal.go | 10 +++++----- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/abci/prepare_proposal.go b/abci/prepare_proposal.go index 925c8a17..a5b34ec4 100644 --- a/abci/prepare_proposal.go +++ b/abci/prepare_proposal.go @@ -17,27 +17,26 @@ func (h *AbciHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { valInfo, err := h.getValidatorSet(ctx, req.Height) if err != nil { - return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + return &abci.ResponsePrepareProposal{Txs: req.Txs}, err } - for _, val := range valInfo { + for i, val := range valInfo { exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, val.ConsensusAddr) if err != nil { - return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + return &abci.ResponsePrepareProposal{Txs: req.Txs}, err } if !exists { - return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + return &abci.ResponsePrepareProposal{Txs: req.Txs}, err } - minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, val.ConsensusAddr) - if err != nil { - return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil - } - voteExtsForGivenBlock[string(val.ConsensusAddr)] = h.fetchVote(targetHeight, string(minaKey)) + + votes := req.LocalLastCommit.Votes + + voteExtsForGivenBlock[string(votes[i].Validator.Address)] = votes[i].ExtensionSignature } if len(voteExtsForGivenBlock) == 0 { - return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + return &abci.ResponsePrepareProposal{Txs: req.Txs}, err } pl := payload{Height: targetHeight, Votes: voteExtsForGivenBlock} @@ -54,6 +53,6 @@ func (h *AbciHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { txs = append(txs, extTx) txs = append(txs, req.Txs...) - return &abci.ResponsePrepareProposal{Txs: [][]byte{}}, nil + return &abci.ResponsePrepareProposal{Txs: txs}, nil } } diff --git a/abci/process_proposal.go b/abci/process_proposal.go index 9a84c843..4f9a6061 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -21,22 +21,22 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { // vote ext reconstruct currentState, err := stakingkeeper.Keeper.GetHistoricalInfo(h.stakingKeeper, ctx, req.GetHeight()-2) if err != nil { - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } valInfo, err := h.getValidatorSet(ctx, req.GetHeight()-1) if err != nil { - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, valInfo, poseidonHash) if err != nil { - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } if nextValidatorSetHash == nil { - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } body := VoteExtensionBody{ @@ -56,7 +56,7 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { currentValidatorStakePower += val.Power } - if float64(signedStakePower) < float64(currentValidatorStakePower)*AcceptanceRatio { + if signedStakePower*3 >= currentValidatorStakePower*2 { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil } From c13255c7f766789645e9ed33bc4a8ca61b94a292 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 27 Apr 2026 17:38:36 +0300 Subject: [PATCH 06/63] feat: initialize vote persistence module --- app/app.go | 9 +- app/app_config.go | 9 + .../votepersistence/module/v1/module.proto | 15 + .../votepersistence/v1/genesis.proto | 17 + .../votepersistence/v1/params.proto | 13 + .../votepersistence/v1/query.proto | 30 + proto/pulsarchain/votepersistence/v1/tx.proto | 40 ++ x/pulsar/types/genesis.pb.go | 7 +- x/pulsar/types/module.pb.go | 5 +- x/pulsar/types/params.pb.go | 7 +- x/pulsar/types/query.pb.go | 7 +- x/pulsar/types/tx.pb.go | 7 +- x/votepersistence/keeper/genesis.go | 25 + x/votepersistence/keeper/genesis_test.go | 24 + x/votepersistence/keeper/keeper.go | 60 ++ x/votepersistence/keeper/keeper_test.go | 56 ++ x/votepersistence/keeper/msg_server.go | 17 + x/votepersistence/keeper/msg_update_params.go | 32 + .../keeper/msg_update_params_test.go | 68 ++ x/votepersistence/keeper/query.go | 17 + x/votepersistence/keeper/query_params.go | 26 + x/votepersistence/keeper/query_params_test.go | 22 + x/votepersistence/module/autocli.go | 35 + x/votepersistence/module/depinject.go | 62 ++ x/votepersistence/module/module.go | 143 +++++ x/votepersistence/module/simulation.go | 34 + x/votepersistence/types/codec.go | 14 + x/votepersistence/types/errors.go | 12 + x/votepersistence/types/expected_keepers.go | 27 + x/votepersistence/types/genesis.go | 14 + x/votepersistence/types/genesis.pb.go | 328 ++++++++++ x/votepersistence/types/genesis_test.go | 37 ++ x/votepersistence/types/keys.go | 19 + x/votepersistence/types/module.pb.go | 325 ++++++++++ x/votepersistence/types/params.go | 17 + x/votepersistence/types/params.pb.go | 293 +++++++++ x/votepersistence/types/query.pb.go | 545 ++++++++++++++++ x/votepersistence/types/query.pb.gw.go | 153 +++++ x/votepersistence/types/tx.pb.go | 604 ++++++++++++++++++ x/votepersistence/types/types.go | 1 + 40 files changed, 3159 insertions(+), 17 deletions(-) create mode 100644 proto/pulsarchain/votepersistence/module/v1/module.proto create mode 100644 proto/pulsarchain/votepersistence/v1/genesis.proto create mode 100644 proto/pulsarchain/votepersistence/v1/params.proto create mode 100644 proto/pulsarchain/votepersistence/v1/query.proto create mode 100644 proto/pulsarchain/votepersistence/v1/tx.proto create mode 100644 x/votepersistence/keeper/genesis.go create mode 100644 x/votepersistence/keeper/genesis_test.go create mode 100644 x/votepersistence/keeper/keeper.go create mode 100644 x/votepersistence/keeper/keeper_test.go create mode 100644 x/votepersistence/keeper/msg_server.go create mode 100644 x/votepersistence/keeper/msg_update_params.go create mode 100644 x/votepersistence/keeper/msg_update_params_test.go create mode 100644 x/votepersistence/keeper/query.go create mode 100644 x/votepersistence/keeper/query_params.go create mode 100644 x/votepersistence/keeper/query_params_test.go create mode 100644 x/votepersistence/module/autocli.go create mode 100644 x/votepersistence/module/depinject.go create mode 100644 x/votepersistence/module/module.go create mode 100644 x/votepersistence/module/simulation.go create mode 100644 x/votepersistence/types/codec.go create mode 100644 x/votepersistence/types/errors.go create mode 100644 x/votepersistence/types/expected_keepers.go create mode 100644 x/votepersistence/types/genesis.go create mode 100644 x/votepersistence/types/genesis.pb.go create mode 100644 x/votepersistence/types/genesis_test.go create mode 100644 x/votepersistence/types/keys.go create mode 100644 x/votepersistence/types/module.pb.go create mode 100644 x/votepersistence/types/params.go create mode 100644 x/votepersistence/types/params.pb.go create mode 100644 x/votepersistence/types/query.pb.go create mode 100644 x/votepersistence/types/query.pb.gw.go create mode 100644 x/votepersistence/types/tx.pb.go create mode 100644 x/votepersistence/types/types.go diff --git a/app/app.go b/app/app.go index b63ee207..f0f85bd8 100644 --- a/app/app.go +++ b/app/app.go @@ -48,6 +48,7 @@ import ( "github.com/node101-io/pulsar-chain/docs" keyregistrymodulekeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" pulsarmodulekeeper "github.com/node101-io/pulsar-chain/x/pulsar/keeper" + votepersistencemodulekeeper "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" ) const ( @@ -100,9 +101,10 @@ type App struct { TransferKeeper ibctransferkeeper.Keeper // simulation manager - sm *module.SimulationManager - PulsarKeeper pulsarmodulekeeper.Keeper - KeyregistryKeeper keyregistrymodulekeeper.Keeper + sm *module.SimulationManager + PulsarKeeper pulsarmodulekeeper.Keeper + KeyregistryKeeper keyregistrymodulekeeper.Keeper + VotepersistenceKeeper votepersistencemodulekeeper.Keeper } func init() { @@ -184,6 +186,7 @@ func New( &app.ParamsKeeper, &app.PulsarKeeper, &app.KeyregistryKeeper, + &app.VotepersistenceKeeper, ); err != nil { panic(err) } diff --git a/app/app_config.go b/app/app_config.go index db90a02e..dc747fa5 100644 --- a/app/app_config.go +++ b/app/app_config.go @@ -7,6 +7,8 @@ import ( keyregistrymoduletypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" _ "github.com/node101-io/pulsar-chain/x/pulsar/module" pulsarmoduletypes "github.com/node101-io/pulsar-chain/x/pulsar/types" + _ "github.com/node101-io/pulsar-chain/x/votepersistence/module" + votepersistencemoduletypes "github.com/node101-io/pulsar-chain/x/votepersistence/types" runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1" appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1" @@ -130,6 +132,7 @@ var ( // chain modules pulsarmoduletypes.ModuleName, keyregistrymoduletypes.ModuleName, + votepersistencemoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/beginBlockers }, EndBlockers: []string{ @@ -140,6 +143,7 @@ var ( // chain modules pulsarmoduletypes.ModuleName, keyregistrymoduletypes.ModuleName, + votepersistencemoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/endBlockers }, // The following is mostly only needed when ModuleName != StoreKey name. @@ -178,6 +182,7 @@ var ( // chain modules pulsarmoduletypes.ModuleName, keyregistrymoduletypes.ModuleName, + votepersistencemoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/initGenesis }, }), @@ -282,6 +287,10 @@ var ( Name: keyregistrymoduletypes.ModuleName, Config: appconfig.WrapAny(&keyregistrymoduletypes.Module{}), }, + { + Name: votepersistencemoduletypes.ModuleName, + Config: appconfig.WrapAny(&votepersistencemoduletypes.Module{}), + }, // this line is used by starport scaffolding # stargate/app/moduleConfig }, }) diff --git a/proto/pulsarchain/votepersistence/module/v1/module.proto b/proto/pulsarchain/votepersistence/module/v1/module.proto new file mode 100644 index 00000000..95cef682 --- /dev/null +++ b/proto/pulsarchain/votepersistence/module/v1/module.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; +package pulsarchain.votepersistence.module.v1; + +import "cosmos/app/v1alpha1/module.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/votepersistence/types"; + +// Module is the config object for the module. +message Module { + option (cosmos.app.v1alpha1.module) = {go_import: "github.com/node101-io/pulsar-chain/x/votepersistence"}; + + // authority defines the custom module authority. + // If not set, defaults to the governance module. + string authority = 1; +} diff --git a/proto/pulsarchain/votepersistence/v1/genesis.proto b/proto/pulsarchain/votepersistence/v1/genesis.proto new file mode 100644 index 00000000..dd13c4a6 --- /dev/null +++ b/proto/pulsarchain/votepersistence/v1/genesis.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package pulsarchain.votepersistence.v1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; +import "pulsarchain/votepersistence/v1/params.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/votepersistence/types"; + +// GenesisState defines the votepersistence module's genesis state. +message GenesisState { + // params defines all the parameters of the module. + Params params = 1 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} diff --git a/proto/pulsarchain/votepersistence/v1/params.proto b/proto/pulsarchain/votepersistence/v1/params.proto new file mode 100644 index 00000000..35085c91 --- /dev/null +++ b/proto/pulsarchain/votepersistence/v1/params.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package pulsarchain.votepersistence.v1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/votepersistence/types"; + +// Params defines the parameters for the module. +message Params { + option (amino.name) = "pulsarchain/x/votepersistence/Params"; + option (gogoproto.equal) = true; +} diff --git a/proto/pulsarchain/votepersistence/v1/query.proto b/proto/pulsarchain/votepersistence/v1/query.proto new file mode 100644 index 00000000..aecc4d2d --- /dev/null +++ b/proto/pulsarchain/votepersistence/v1/query.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; +package pulsarchain.votepersistence.v1; + +import "amino/amino.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "pulsarchain/votepersistence/v1/params.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/votepersistence/types"; + +// Query defines the gRPC querier service. +service Query { + // Parameters queries the parameters of the module. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/node101-io/pulsar-chain/votepersistence/v1/params"; + } +} + +// QueryParamsRequest is request type for the Query/Params RPC method. +message QueryParamsRequest {} + +// QueryParamsResponse is response type for the Query/Params RPC method. +message QueryParamsResponse { + // params holds all the parameters of this module. + Params params = 1 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} diff --git a/proto/pulsarchain/votepersistence/v1/tx.proto b/proto/pulsarchain/votepersistence/v1/tx.proto new file mode 100644 index 00000000..dd98a36c --- /dev/null +++ b/proto/pulsarchain/votepersistence/v1/tx.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package pulsarchain.votepersistence.v1; + +import "amino/amino.proto"; +import "cosmos/msg/v1/msg.proto"; +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "pulsarchain/votepersistence/v1/params.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/votepersistence/types"; + +// Msg defines the Msg service. +service Msg { + option (cosmos.msg.v1.service) = true; + + // UpdateParams defines a (governance) operation for updating the module + // parameters. The authority defaults to the x/gov module account. + rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); +} + +// MsgUpdateParams is the Msg/UpdateParams request type. +message MsgUpdateParams { + option (cosmos.msg.v1.signer) = "authority"; + option (amino.name) = "pulsarchain/x/votepersistence/MsgUpdateParams"; + + // authority is the address that controls the module (defaults to x/gov unless overwritten). + string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // params defines the module parameters to update. + // + // NOTE: All parameters must be supplied. + Params params = 2 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} + +// MsgUpdateParamsResponse defines the response structure for executing a +// MsgUpdateParams message. +message MsgUpdateParamsResponse {} diff --git a/x/pulsar/types/genesis.pb.go b/x/pulsar/types/genesis.pb.go index acfbe019..65be9de9 100644 --- a/x/pulsar/types/genesis.pb.go +++ b/x/pulsar/types/genesis.pb.go @@ -5,12 +5,13 @@ package types import ( fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/module.pb.go b/x/pulsar/types/module.pb.go index b7ffd5c3..eeab9504 100644 --- a/x/pulsar/types/module.pb.go +++ b/x/pulsar/types/module.pb.go @@ -4,12 +4,13 @@ package types import ( - _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "cosmossdk.io/api/cosmos/app/v1alpha1" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/params.pb.go b/x/pulsar/types/params.pb.go index 0480a17b..e7a05515 100644 --- a/x/pulsar/types/params.pb.go +++ b/x/pulsar/types/params.pb.go @@ -5,12 +5,13 @@ package types import ( fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/query.pb.go b/x/pulsar/types/query.pb.go index 0c09f00a..8df04fb5 100644 --- a/x/pulsar/types/query.pb.go +++ b/x/pulsar/types/query.pb.go @@ -6,6 +6,10 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -15,9 +19,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/tx.pb.go b/x/pulsar/types/tx.pb.go index e3271589..2f343e52 100644 --- a/x/pulsar/types/tx.pb.go +++ b/x/pulsar/types/tx.pb.go @@ -6,6 +6,10 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -15,9 +19,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/keeper/genesis.go b/x/votepersistence/keeper/genesis.go new file mode 100644 index 00000000..5b53e605 --- /dev/null +++ b/x/votepersistence/keeper/genesis.go @@ -0,0 +1,25 @@ +package keeper + +import ( + "context" + + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +// InitGenesis initializes the module's state from a provided genesis state. +func (k Keeper) InitGenesis(ctx context.Context, genState types.GenesisState) error { + return k.Params.Set(ctx, genState.Params) +} + +// ExportGenesis returns the module's exported genesis. +func (k Keeper) ExportGenesis(ctx context.Context) (*types.GenesisState, error) { + var err error + + genesis := types.DefaultGenesis() + genesis.Params, err = k.Params.Get(ctx) + if err != nil { + return nil, err + } + + return genesis, nil +} diff --git a/x/votepersistence/keeper/genesis_test.go b/x/votepersistence/keeper/genesis_test.go new file mode 100644 index 00000000..ecfbbac5 --- /dev/null +++ b/x/votepersistence/keeper/genesis_test.go @@ -0,0 +1,24 @@ +package keeper_test + +import ( + "testing" + + "github.com/node101-io/pulsar-chain/x/votepersistence/types" + + "github.com/stretchr/testify/require" +) + +func TestGenesis(t *testing.T) { + genesisState := types.GenesisState{ + Params: types.DefaultParams(), + } + + f := initFixture(t) + err := f.keeper.InitGenesis(f.ctx, genesisState) + require.NoError(t, err) + got, err := f.keeper.ExportGenesis(f.ctx) + require.NoError(t, err) + require.NotNil(t, got) + + require.EqualExportedValues(t, genesisState.Params, got.Params) +} diff --git a/x/votepersistence/keeper/keeper.go b/x/votepersistence/keeper/keeper.go new file mode 100644 index 00000000..ea31ae1c --- /dev/null +++ b/x/votepersistence/keeper/keeper.go @@ -0,0 +1,60 @@ +package keeper + +import ( + "fmt" + + "cosmossdk.io/collections" + "cosmossdk.io/core/address" + corestore "cosmossdk.io/core/store" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +type Keeper struct { + storeService corestore.KVStoreService + cdc codec.Codec + addressCodec address.Codec + // Address capable of executing a MsgUpdateParams message. + // Typically, this should be the x/gov module account. + authority []byte + + Schema collections.Schema + Params collections.Item[types.Params] +} + +func NewKeeper( + storeService corestore.KVStoreService, + cdc codec.Codec, + addressCodec address.Codec, + authority []byte, + +) Keeper { + if _, err := addressCodec.BytesToString(authority); err != nil { + panic(fmt.Sprintf("invalid authority address %s: %s", authority, err)) + } + + sb := collections.NewSchemaBuilder(storeService) + + k := Keeper{ + storeService: storeService, + cdc: cdc, + addressCodec: addressCodec, + authority: authority, + + Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), + } + + schema, err := sb.Build() + if err != nil { + panic(err) + } + k.Schema = schema + + return k +} + +// GetAuthority returns the module's authority. +func (k Keeper) GetAuthority() []byte { + return k.authority +} diff --git a/x/votepersistence/keeper/keeper_test.go b/x/votepersistence/keeper/keeper_test.go new file mode 100644 index 00000000..250ed52c --- /dev/null +++ b/x/votepersistence/keeper/keeper_test.go @@ -0,0 +1,56 @@ +package keeper_test + +import ( + "context" + "testing" + + "cosmossdk.io/core/address" + storetypes "cosmossdk.io/store/types" + addresscodec "github.com/cosmos/cosmos-sdk/codec/address" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" + module "github.com/node101-io/pulsar-chain/x/votepersistence/module" + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +type fixture struct { + ctx context.Context + keeper keeper.Keeper + addressCodec address.Codec +} + +func initFixture(t *testing.T) *fixture { + t.Helper() + + encCfg := moduletestutil.MakeTestEncodingConfig(module.AppModule{}) + addressCodec := addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + storeKey := storetypes.NewKVStoreKey(types.StoreKey) + + storeService := runtime.NewKVStoreService(storeKey) + ctx := testutil.DefaultContextWithDB(t, storeKey, storetypes.NewTransientStoreKey("transient_test")).Ctx + + authority := authtypes.NewModuleAddress(types.GovModuleName) + + k := keeper.NewKeeper( + storeService, + encCfg.Codec, + addressCodec, + authority, + ) + + // Initialize params + if err := k.Params.Set(ctx, types.DefaultParams()); err != nil { + t.Fatalf("failed to set params: %v", err) + } + + return &fixture{ + ctx: ctx, + keeper: k, + addressCodec: addressCodec, + } +} diff --git a/x/votepersistence/keeper/msg_server.go b/x/votepersistence/keeper/msg_server.go new file mode 100644 index 00000000..5e538c2f --- /dev/null +++ b/x/votepersistence/keeper/msg_server.go @@ -0,0 +1,17 @@ +package keeper + +import ( + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{Keeper: keeper} +} + +var _ types.MsgServer = msgServer{} diff --git a/x/votepersistence/keeper/msg_update_params.go b/x/votepersistence/keeper/msg_update_params.go new file mode 100644 index 00000000..aef1db35 --- /dev/null +++ b/x/votepersistence/keeper/msg_update_params.go @@ -0,0 +1,32 @@ +package keeper + +import ( + "bytes" + "context" + + errorsmod "cosmossdk.io/errors" + + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +func (k msgServer) UpdateParams(ctx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { + authority, err := k.addressCodec.StringToBytes(req.Authority) + if err != nil { + return nil, errorsmod.Wrap(err, "invalid authority address") + } + + if !bytes.Equal(k.GetAuthority(), authority) { + expectedAuthorityStr, _ := k.addressCodec.BytesToString(k.GetAuthority()) + return nil, errorsmod.Wrapf(types.ErrInvalidSigner, "invalid authority; expected %s, got %s", expectedAuthorityStr, req.Authority) + } + + if err := req.Params.Validate(); err != nil { + return nil, err + } + + if err := k.Params.Set(ctx, req.Params); err != nil { + return nil, err + } + + return &types.MsgUpdateParamsResponse{}, nil +} diff --git a/x/votepersistence/keeper/msg_update_params_test.go b/x/votepersistence/keeper/msg_update_params_test.go new file mode 100644 index 00000000..c9818916 --- /dev/null +++ b/x/votepersistence/keeper/msg_update_params_test.go @@ -0,0 +1,68 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +func TestMsgUpdateParams(t *testing.T) { + f := initFixture(t) + ms := keeper.NewMsgServerImpl(f.keeper) + + params := types.DefaultParams() + require.NoError(t, f.keeper.Params.Set(f.ctx, params)) + + authorityStr, err := f.addressCodec.BytesToString(f.keeper.GetAuthority()) + require.NoError(t, err) + + // default params + testCases := []struct { + name string + input *types.MsgUpdateParams + expErr bool + expErrMsg string + }{ + { + name: "invalid authority", + input: &types.MsgUpdateParams{ + Authority: "invalid", + Params: params, + }, + expErr: true, + expErrMsg: "invalid authority", + }, + { + name: "send enabled param", + input: &types.MsgUpdateParams{ + Authority: authorityStr, + Params: types.Params{}, + }, + expErr: false, + }, + { + name: "all good", + input: &types.MsgUpdateParams{ + Authority: authorityStr, + Params: params, + }, + expErr: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + _, err := ms.UpdateParams(f.ctx, tc.input) + + if tc.expErr { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErrMsg) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/votepersistence/keeper/query.go b/x/votepersistence/keeper/query.go new file mode 100644 index 00000000..58ad2a9e --- /dev/null +++ b/x/votepersistence/keeper/query.go @@ -0,0 +1,17 @@ +package keeper + +import ( + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +var _ types.QueryServer = queryServer{} + +// NewQueryServerImpl returns an implementation of the QueryServer interface +// for the provided Keeper. +func NewQueryServerImpl(k Keeper) types.QueryServer { + return queryServer{k} +} + +type queryServer struct { + k Keeper +} diff --git a/x/votepersistence/keeper/query_params.go b/x/votepersistence/keeper/query_params.go new file mode 100644 index 00000000..3c86597c --- /dev/null +++ b/x/votepersistence/keeper/query_params.go @@ -0,0 +1,26 @@ +package keeper + +import ( + "context" + "errors" + + "cosmossdk.io/collections" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +func (q queryServer) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + params, err := q.k.Params.Get(ctx) + if err != nil && !errors.Is(err, collections.ErrNotFound) { + return nil, status.Error(codes.Internal, "internal error") + } + + return &types.QueryParamsResponse{Params: params}, nil +} diff --git a/x/votepersistence/keeper/query_params_test.go b/x/votepersistence/keeper/query_params_test.go new file mode 100644 index 00000000..0df3eb53 --- /dev/null +++ b/x/votepersistence/keeper/query_params_test.go @@ -0,0 +1,22 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +func TestParamsQuery(t *testing.T) { + f := initFixture(t) + + qs := keeper.NewQueryServerImpl(f.keeper) + params := types.DefaultParams() + require.NoError(t, f.keeper.Params.Set(f.ctx, params)) + + response, err := qs.Params(f.ctx, &types.QueryParamsRequest{}) + require.NoError(t, err) + require.Equal(t, &types.QueryParamsResponse{Params: params}, response) +} diff --git a/x/votepersistence/module/autocli.go b/x/votepersistence/module/autocli.go new file mode 100644 index 00000000..6fc3fdaf --- /dev/null +++ b/x/votepersistence/module/autocli.go @@ -0,0 +1,35 @@ +package votepersistence + +import ( + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. +func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { + return &autocliv1.ModuleOptions{ + Query: &autocliv1.ServiceCommandDescriptor{ + Service: types.Query_serviceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Params", + Use: "params", + Short: "Shows the parameters of the module", + }, + // this line is used by ignite scaffolding # autocli/query + }, + }, + Tx: &autocliv1.ServiceCommandDescriptor{ + Service: types.Msg_serviceDesc.ServiceName, + EnhanceCustomCommand: true, // only required if you want to use the custom command + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "UpdateParams", + Skip: true, // skipped because authority gated + }, + // this line is used by ignite scaffolding # autocli/tx + }, + }, + } +} diff --git a/x/votepersistence/module/depinject.go b/x/votepersistence/module/depinject.go new file mode 100644 index 00000000..5a393590 --- /dev/null +++ b/x/votepersistence/module/depinject.go @@ -0,0 +1,62 @@ +package votepersistence + +import ( + "cosmossdk.io/core/address" + "cosmossdk.io/core/appmodule" + "cosmossdk.io/core/store" + "cosmossdk.io/depinject" + "cosmossdk.io/depinject/appconfig" + "github.com/cosmos/cosmos-sdk/codec" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +var _ depinject.OnePerModuleType = AppModule{} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (AppModule) IsOnePerModuleType() {} + +func init() { + appconfig.Register( + &types.Module{}, + appconfig.Provide(ProvideModule), + ) +} + +type ModuleInputs struct { + depinject.In + + Config *types.Module + StoreService store.KVStoreService + Cdc codec.Codec + AddressCodec address.Codec + + AuthKeeper types.AuthKeeper + BankKeeper types.BankKeeper +} + +type ModuleOutputs struct { + depinject.Out + + VotepersistenceKeeper keeper.Keeper + Module appmodule.AppModule +} + +func ProvideModule(in ModuleInputs) ModuleOutputs { + // default to governance authority if not provided + authority := authtypes.NewModuleAddress(types.GovModuleName) + if in.Config.Authority != "" { + authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) + } + k := keeper.NewKeeper( + in.StoreService, + in.Cdc, + in.AddressCodec, + authority, + ) + m := NewAppModule(in.Cdc, k, in.AuthKeeper, in.BankKeeper) + + return ModuleOutputs{VotepersistenceKeeper: k, Module: m} +} diff --git a/x/votepersistence/module/module.go b/x/votepersistence/module/module.go new file mode 100644 index 00000000..b1918551 --- /dev/null +++ b/x/votepersistence/module/module.go @@ -0,0 +1,143 @@ +package votepersistence + +import ( + "context" + "encoding/json" + "fmt" + + "cosmossdk.io/core/appmodule" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "google.golang.org/grpc" + + "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +var ( + _ module.AppModuleBasic = (*AppModule)(nil) + _ module.AppModule = (*AppModule)(nil) + _ module.HasGenesis = (*AppModule)(nil) + + _ appmodule.AppModule = (*AppModule)(nil) + _ appmodule.HasBeginBlocker = (*AppModule)(nil) + _ appmodule.HasEndBlocker = (*AppModule)(nil) +) + +// AppModule implements the AppModule interface that defines the inter-dependent methods that modules need to implement +type AppModule struct { + cdc codec.Codec + keeper keeper.Keeper + authKeeper types.AuthKeeper + bankKeeper types.BankKeeper +} + +func NewAppModule( + cdc codec.Codec, + keeper keeper.Keeper, + authKeeper types.AuthKeeper, + bankKeeper types.BankKeeper, +) AppModule { + return AppModule{ + cdc: cdc, + keeper: keeper, + authKeeper: authKeeper, + bankKeeper: bankKeeper, + } +} + +// IsAppModule implements the appmodule.AppModule interface. +func (AppModule) IsAppModule() {} + +// Name returns the name of the module as a string. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec registers the amino codec +func (AppModule) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module. +func (AppModule) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + if err := types.RegisterQueryHandlerClient(clientCtx.CmdContext, mux, types.NewQueryClient(clientCtx)); err != nil { + panic(err) + } +} + +// RegisterInterfaces registers a module's interface types and their concrete implementations as proto.Message. +func (AppModule) RegisterInterfaces(registrar codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registrar) +} + +// RegisterServices registers a gRPC query service to respond to the module-specific gRPC queries +func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error { + types.RegisterMsgServer(registrar, keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(registrar, keeper.NewQueryServerImpl(am.keeper)) + + return nil +} + +// DefaultGenesis returns a default GenesisState for the module, marshalled to json.RawMessage. +// The default GenesisState need to be defined by the module developer and is primarily used for testing. +func (am AppModule) DefaultGenesis(codec.JSONCodec) json.RawMessage { + return am.cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +// ValidateGenesis used to validate the GenesisState, given in its json.RawMessage form. +func (am AppModule) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { + var genState types.GenesisState + if err := am.cdc.UnmarshalJSON(bz, &genState); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + + return genState.Validate() +} + +// InitGenesis performs the module's genesis initialization. It returns no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, _ codec.JSONCodec, gs json.RawMessage) { + var genState types.GenesisState + // Initialize global index to index in genesis state + if err := am.cdc.UnmarshalJSON(gs, &genState); err != nil { + panic(fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)) + } + + if err := am.keeper.InitGenesis(ctx, genState); err != nil { + panic(fmt.Errorf("failed to initialize %s genesis state: %w", types.ModuleName, err)) + } +} + +// ExportGenesis returns the module's exported genesis state as raw JSON bytes. +func (am AppModule) ExportGenesis(ctx sdk.Context, _ codec.JSONCodec) json.RawMessage { + genState, err := am.keeper.ExportGenesis(ctx) + if err != nil { + panic(fmt.Errorf("failed to export %s genesis state: %w", types.ModuleName, err)) + } + + bz, err := am.cdc.MarshalJSON(genState) + if err != nil { + panic(fmt.Errorf("failed to marshal %s genesis state: %w", types.ModuleName, err)) + } + + return bz +} + +// ConsensusVersion is a sequence number for state-breaking change of the module. +// It should be incremented on each consensus-breaking change introduced by the module. +// To avoid wrong/empty versions, the initial version should be set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } + +// BeginBlock contains the logic that is automatically triggered at the beginning of each block. +// The begin block implementation is optional. +func (am AppModule) BeginBlock(_ context.Context) error { + return nil +} + +// EndBlock contains the logic that is automatically triggered at the end of each block. +// The end block implementation is optional. +func (am AppModule) EndBlock(_ context.Context) error { + return nil +} diff --git a/x/votepersistence/module/simulation.go b/x/votepersistence/module/simulation.go new file mode 100644 index 00000000..2c2c708f --- /dev/null +++ b/x/votepersistence/module/simulation.go @@ -0,0 +1,34 @@ +package votepersistence + +import ( + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/node101-io/pulsar-chain/x/votepersistence/types" +) + +// GenerateGenesisState creates a randomized GenState of the module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + accs := make([]string, len(simState.Accounts)) + for i, acc := range simState.Accounts { + accs[i] = acc.Address.String() + } + votepersistenceGenesis := types.GenesisState{ + Params: types.DefaultParams(), + } + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&votepersistenceGenesis) +} + +// RegisterStoreDecoder registers a decoder. +func (am AppModule) RegisterStoreDecoder(_ simtypes.StoreDecoderRegistry) {} + +// WeightedOperations returns the all the gov module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + operations := make([]simtypes.WeightedOperation, 0) + return operations +} + +// ProposalMsgs returns msgs used for governance proposals for simulations. +func (am AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { + return []simtypes.WeightedProposalMsg{} +} diff --git a/x/votepersistence/types/codec.go b/x/votepersistence/types/codec.go new file mode 100644 index 00000000..56398f5e --- /dev/null +++ b/x/votepersistence/types/codec.go @@ -0,0 +1,14 @@ +package types + +import ( + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +func RegisterInterfaces(registrar codectypes.InterfaceRegistry) { + registrar.RegisterImplementations((*sdk.Msg)(nil), + &MsgUpdateParams{}, + ) + msgservice.RegisterMsgServiceDesc(registrar, &_Msg_serviceDesc) +} diff --git a/x/votepersistence/types/errors.go b/x/votepersistence/types/errors.go new file mode 100644 index 00000000..c489914c --- /dev/null +++ b/x/votepersistence/types/errors.go @@ -0,0 +1,12 @@ +package types + +// DONTCOVER + +import ( + "cosmossdk.io/errors" +) + +// x/votepersistence module sentinel errors +var ( + ErrInvalidSigner = errors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") +) diff --git a/x/votepersistence/types/expected_keepers.go b/x/votepersistence/types/expected_keepers.go new file mode 100644 index 00000000..b175461c --- /dev/null +++ b/x/votepersistence/types/expected_keepers.go @@ -0,0 +1,27 @@ +package types + +import ( + "context" + + "cosmossdk.io/core/address" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// AuthKeeper defines the expected interface for the Auth module. +type AuthKeeper interface { + AddressCodec() address.Codec + GetAccount(context.Context, sdk.AccAddress) sdk.AccountI // only used for simulation + // Methods imported from account should be defined here +} + +// BankKeeper defines the expected interface for the Bank module. +type BankKeeper interface { + SpendableCoins(context.Context, sdk.AccAddress) sdk.Coins + // Methods imported from bank should be defined here +} + +// ParamSubspace defines the expected Subspace interface for parameters. +type ParamSubspace interface { + Get(context.Context, []byte, interface{}) + Set(context.Context, []byte, interface{}) +} diff --git a/x/votepersistence/types/genesis.go b/x/votepersistence/types/genesis.go new file mode 100644 index 00000000..9d633ecd --- /dev/null +++ b/x/votepersistence/types/genesis.go @@ -0,0 +1,14 @@ +package types + +// DefaultGenesis returns the default genesis state +func DefaultGenesis() *GenesisState { + return &GenesisState{ + Params: DefaultParams(), + } +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + return gs.Params.Validate() +} diff --git a/x/votepersistence/types/genesis.pb.go b/x/votepersistence/types/genesis.pb.go new file mode 100644 index 00000000..9c48d742 --- /dev/null +++ b/x/votepersistence/types/genesis.pb.go @@ -0,0 +1,328 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/votepersistence/v1/genesis.proto + +package types + +import ( + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the votepersistence module's genesis state. +type GenesisState struct { + // params defines all the parameters of the module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_1055d46b0af7944d, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "pulsarchain.votepersistence.v1.GenesisState") +} + +func init() { + proto.RegisterFile("pulsarchain/votepersistence/v1/genesis.proto", fileDescriptor_1055d46b0af7944d) +} + +var fileDescriptor_1055d46b0af7944d = []byte{ + // 234 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x29, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x2f, 0xcb, 0x2f, 0x49, 0x2d, 0x48, 0x2d, 0x2a, + 0xce, 0x2c, 0x2e, 0x49, 0xcd, 0x4b, 0x4e, 0xd5, 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, + 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x43, 0x52, 0xad, 0x87, 0xa6, 0x5a, + 0xaf, 0xcc, 0x50, 0x4a, 0x30, 0x31, 0x37, 0x33, 0x2f, 0x5f, 0x1f, 0x4c, 0x42, 0xb4, 0x48, 0x89, + 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x99, 0xfa, 0x20, 0x16, 0x54, 0x54, 0x9b, 0x80, 0xb5, 0x05, 0x89, + 0x45, 0x89, 0xb9, 0x50, 0x5b, 0x95, 0x22, 0xb9, 0x78, 0xdc, 0x21, 0xce, 0x08, 0x2e, 0x49, 0x2c, + 0x49, 0x15, 0xf2, 0xe4, 0x62, 0x83, 0xc8, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x1b, 0xa9, 0xe9, + 0xe1, 0x77, 0x96, 0x5e, 0x00, 0x58, 0xb5, 0x13, 0xe7, 0x89, 0x7b, 0xf2, 0x0c, 0x2b, 0x9e, 0x6f, + 0xd0, 0x62, 0x0c, 0x82, 0x1a, 0xe0, 0x14, 0x72, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, + 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, + 0x0c, 0x51, 0x56, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x79, 0xf9, + 0x29, 0xa9, 0x86, 0x06, 0x86, 0xba, 0x99, 0xf9, 0xfa, 0x10, 0x9b, 0x74, 0x21, 0x0e, 0xaf, 0xc0, + 0x70, 0x7a, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0xdd, 0xc6, 0x80, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x14, 0x23, 0xa4, 0xc5, 0x5d, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/votepersistence/types/genesis_test.go b/x/votepersistence/types/genesis_test.go new file mode 100644 index 00000000..566e199b --- /dev/null +++ b/x/votepersistence/types/genesis_test.go @@ -0,0 +1,37 @@ +package types_test + +import ( + "testing" + + "github.com/node101-io/pulsar-chain/x/votepersistence/types" + "github.com/stretchr/testify/require" +) + +func TestGenesisState_Validate(t *testing.T) { + tests := []struct { + desc string + genState *types.GenesisState + valid bool + }{ + { + desc: "default is valid", + genState: types.DefaultGenesis(), + valid: true, + }, + { + desc: "valid genesis state", + genState: &types.GenesisState{}, + valid: true, + }, + } + for _, tc := range tests { + t.Run(tc.desc, func(t *testing.T) { + err := tc.genState.Validate() + if tc.valid { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/x/votepersistence/types/keys.go b/x/votepersistence/types/keys.go new file mode 100644 index 00000000..08def311 --- /dev/null +++ b/x/votepersistence/types/keys.go @@ -0,0 +1,19 @@ +package types + +import "cosmossdk.io/collections" + +const ( + // ModuleName defines the module name + ModuleName = "votepersistence" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // GovModuleName duplicates the gov module's name to avoid a dependency with x/gov. + // It should be synced with the gov module's name if it is ever changed. + // See: https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/x/gov/types/keys.go#L9 + GovModuleName = "gov" +) + +// ParamsKey is the prefix to retrieve all Params +var ParamsKey = collections.NewPrefix("p_votepersistence") diff --git a/x/votepersistence/types/module.pb.go b/x/votepersistence/types/module.pb.go new file mode 100644 index 00000000..15faa0b1 --- /dev/null +++ b/x/votepersistence/types/module.pb.go @@ -0,0 +1,325 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/votepersistence/module/v1/module.proto + +package types + +import ( + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "cosmossdk.io/api/cosmos/app/v1alpha1" + proto "github.com/cosmos/gogoproto/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Module is the config object for the module. +type Module struct { + // authority defines the custom module authority. + // If not set, defaults to the governance module. + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` +} + +func (m *Module) Reset() { *m = Module{} } +func (m *Module) String() string { return proto.CompactTextString(m) } +func (*Module) ProtoMessage() {} +func (*Module) Descriptor() ([]byte, []int) { + return fileDescriptor_c3d7f592efedc28c, []int{0} +} +func (m *Module) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Module) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Module.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 *Module) XXX_Merge(src proto.Message) { + xxx_messageInfo_Module.Merge(m, src) +} +func (m *Module) XXX_Size() int { + return m.Size() +} +func (m *Module) XXX_DiscardUnknown() { + xxx_messageInfo_Module.DiscardUnknown(m) +} + +var xxx_messageInfo_Module proto.InternalMessageInfo + +func (m *Module) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func init() { + proto.RegisterType((*Module)(nil), "pulsarchain.votepersistence.module.v1.Module") +} + +func init() { + proto.RegisterFile("pulsarchain/votepersistence/module/v1/module.proto", fileDescriptor_c3d7f592efedc28c) +} + +var fileDescriptor_c3d7f592efedc28c = []byte{ + // 219 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x2a, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x2f, 0xcb, 0x2f, 0x49, 0x2d, 0x48, 0x2d, 0x2a, + 0xce, 0x2c, 0x2e, 0x49, 0xcd, 0x4b, 0x4e, 0xd5, 0xcf, 0xcd, 0x4f, 0x29, 0xcd, 0x49, 0xd5, 0x2f, + 0x33, 0x84, 0xb2, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0x54, 0x91, 0xf4, 0xe8, 0xa1, 0xe9, + 0xd1, 0x83, 0xaa, 0x2c, 0x33, 0x94, 0x52, 0x48, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0xd6, 0x4f, 0x2c, + 0x28, 0xd0, 0x2f, 0x33, 0x4c, 0xcc, 0x29, 0xc8, 0x48, 0x44, 0x35, 0x48, 0x29, 0x85, 0x8b, 0xcd, + 0x17, 0xcc, 0x17, 0x92, 0xe1, 0xe2, 0x4c, 0x2c, 0x2d, 0xc9, 0xc8, 0x2f, 0xca, 0x2c, 0xa9, 0x94, + 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x42, 0x08, 0x58, 0xd9, 0xec, 0x3a, 0x30, 0xed, 0x16, 0xa3, + 0x19, 0x97, 0x49, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x5e, 0x7e, + 0x4a, 0xaa, 0xa1, 0x81, 0xa1, 0x6e, 0x66, 0xbe, 0x3e, 0xc4, 0x39, 0xba, 0x10, 0x3f, 0x54, 0xa0, + 0xfb, 0xc2, 0x29, 0xe4, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, + 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xac, 0xc8, + 0x31, 0x4f, 0xbf, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0xec, 0x05, 0x63, 0x40, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x6d, 0xa9, 0xcf, 0xf9, 0x41, 0x01, 0x00, 0x00, +} + +func (m *Module) 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 *Module) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Module) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintModule(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintModule(dAtA []byte, offset int, v uint64) int { + offset -= sovModule(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Module) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovModule(uint64(l)) + } + return n +} + +func sovModule(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozModule(x uint64) (n int) { + return sovModule(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Module) 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 ErrIntOverflowModule + } + 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: Module: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Module: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModule + } + 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 ErrInvalidLengthModule + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModule + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipModule(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModule + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipModule(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModule + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModule + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModule + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthModule + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupModule + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthModule + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthModule = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowModule = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupModule = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/votepersistence/types/params.go b/x/votepersistence/types/params.go new file mode 100644 index 00000000..d7e00501 --- /dev/null +++ b/x/votepersistence/types/params.go @@ -0,0 +1,17 @@ +package types + +// NewParams creates a new Params instance. +func NewParams() Params { + return Params{} +} + +// DefaultParams returns a default set of parameters. +func DefaultParams() Params { + return NewParams() +} + +// Validate validates the set of params. +func (p Params) Validate() error { + + return nil +} diff --git a/x/votepersistence/types/params.pb.go b/x/votepersistence/types/params.pb.go new file mode 100644 index 00000000..db7a5855 --- /dev/null +++ b/x/votepersistence/types/params.pb.go @@ -0,0 +1,293 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/votepersistence/v1/params.proto + +package types + +import ( + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Params defines the parameters for the module. +type Params struct { +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_7d43c53e6aafc30b, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func init() { + proto.RegisterType((*Params)(nil), "pulsarchain.votepersistence.v1.Params") +} + +func init() { + proto.RegisterFile("pulsarchain/votepersistence/v1/params.proto", fileDescriptor_7d43c53e6aafc30b) +} + +var fileDescriptor_7d43c53e6aafc30b = []byte{ + // 197 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2e, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x2f, 0xcb, 0x2f, 0x49, 0x2d, 0x48, 0x2d, 0x2a, + 0xce, 0x2c, 0x2e, 0x49, 0xcd, 0x4b, 0x4e, 0xd5, 0x2f, 0x33, 0xd4, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, + 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x43, 0x52, 0xac, 0x87, 0xa6, 0x58, 0xaf, + 0xcc, 0x50, 0x4a, 0x30, 0x31, 0x37, 0x33, 0x2f, 0x5f, 0x1f, 0x4c, 0x42, 0xb4, 0x48, 0x89, 0xa4, + 0xe7, 0xa7, 0xe7, 0x83, 0x99, 0xfa, 0x20, 0x16, 0x44, 0x54, 0xc9, 0x9c, 0x8b, 0x2d, 0x00, 0x6c, + 0xb0, 0x95, 0xee, 0x8b, 0x05, 0xf2, 0x8c, 0x5d, 0xcf, 0x37, 0x68, 0xa9, 0x20, 0x3b, 0xa4, 0x02, + 0xc3, 0x29, 0x10, 0xe5, 0x4e, 0x21, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, + 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, + 0x65, 0x95, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x9f, 0x97, 0x9f, 0x92, + 0x6a, 0x68, 0x60, 0xa8, 0x9b, 0x99, 0xaf, 0x0f, 0x31, 0x55, 0x17, 0x97, 0xb1, 0x25, 0x95, 0x05, + 0xa9, 0xc5, 0x49, 0x6c, 0x60, 0x57, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x76, 0x79, 0x99, + 0xc3, 0x0d, 0x01, 0x00, 0x00, +} + +func (this *Params) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Params) + if !ok { + that2, ok := that.(Params) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintParams(dAtA []byte, offset int, v uint64) int { + offset -= sovParams(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovParams(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozParams(x uint64) (n int) { + return sovParams(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) 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 ErrIntOverflowParams + } + 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: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipParams(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthParams + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupParams + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthParams + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthParams = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowParams = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupParams = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/votepersistence/types/query.pb.go b/x/votepersistence/types/query.pb.go new file mode 100644 index 00000000..7f0e6273 --- /dev/null +++ b/x/votepersistence/types/query.pb.go @@ -0,0 +1,545 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/votepersistence/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryParamsRequest is request type for the Query/Params RPC method. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2c9976ecef977273, []int{0} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.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 *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse is response type for the Query/Params RPC method. +type QueryParamsResponse struct { + // params holds all the parameters of this module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2c9976ecef977273, []int{1} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.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 *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*QueryParamsRequest)(nil), "pulsarchain.votepersistence.v1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "pulsarchain.votepersistence.v1.QueryParamsResponse") +} + +func init() { + proto.RegisterFile("pulsarchain/votepersistence/v1/query.proto", fileDescriptor_2c9976ecef977273) +} + +var fileDescriptor_2c9976ecef977273 = []byte{ + // 342 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xb1, 0x4a, 0x3b, 0x41, + 0x10, 0xc6, 0x6f, 0xff, 0xf0, 0x0f, 0x78, 0x56, 0x9e, 0x29, 0x24, 0xc8, 0x2a, 0x29, 0x44, 0x22, + 0xb9, 0xf5, 0x2e, 0x56, 0x29, 0xd3, 0xd9, 0x69, 0xb0, 0xb2, 0x72, 0xef, 0x1c, 0x2e, 0x0b, 0xb9, + 0x9d, 0xcd, 0xed, 0xde, 0x61, 0x5a, 0x9f, 0x40, 0xf0, 0x25, 0x6c, 0x04, 0x3b, 0x5f, 0x21, 0x65, + 0xc0, 0xc6, 0x4a, 0x24, 0x11, 0x7c, 0x0d, 0xc9, 0xed, 0x15, 0x6a, 0xd0, 0x60, 0xb3, 0x0c, 0xdf, + 0x7e, 0xdf, 0x6f, 0x66, 0x76, 0xdd, 0x96, 0xca, 0x87, 0x9a, 0x67, 0xf1, 0x80, 0x0b, 0xc9, 0x0a, + 0x34, 0xa0, 0x20, 0xd3, 0x42, 0x1b, 0x90, 0x31, 0xb0, 0x22, 0x60, 0xa3, 0x1c, 0xb2, 0xb1, 0xaf, + 0x32, 0x34, 0xe8, 0xd1, 0x4f, 0x5e, 0xff, 0x9b, 0xd7, 0x2f, 0x82, 0xc6, 0x06, 0x4f, 0x85, 0x44, + 0x56, 0x9e, 0x36, 0xd2, 0xa8, 0x27, 0x98, 0x60, 0x59, 0xb2, 0x45, 0x55, 0xa9, 0xdb, 0x09, 0x62, + 0x32, 0x04, 0xc6, 0x95, 0x60, 0x5c, 0x4a, 0x34, 0xdc, 0x08, 0x94, 0xba, 0xba, 0x6d, 0xc5, 0xa8, + 0x53, 0xd4, 0x2c, 0xe2, 0x1a, 0x6c, 0x7f, 0x56, 0x04, 0x11, 0x18, 0x1e, 0x30, 0xc5, 0x13, 0x21, + 0x4b, 0x73, 0xe5, 0x3d, 0x58, 0x31, 0xbe, 0xe2, 0x19, 0x4f, 0x2b, 0x70, 0xb3, 0xee, 0x7a, 0xa7, + 0x0b, 0xdc, 0x49, 0x29, 0xf6, 0x61, 0x94, 0x83, 0x36, 0xcd, 0x0b, 0x77, 0xf3, 0x8b, 0xaa, 0x15, + 0x4a, 0x0d, 0xde, 0xb1, 0x5b, 0xb3, 0xe1, 0x2d, 0xb2, 0x4b, 0xf6, 0xd7, 0xc3, 0x3d, 0xff, 0xf7, + 0xed, 0x7d, 0x9b, 0xef, 0xad, 0x4d, 0x5e, 0x76, 0x9c, 0xbb, 0xf7, 0x87, 0x16, 0xe9, 0x57, 0x80, + 0xf0, 0x91, 0xb8, 0xff, 0xcb, 0x16, 0xde, 0x3d, 0x71, 0x6b, 0xd6, 0xe7, 0x85, 0xab, 0x78, 0xcb, + 0xa3, 0x36, 0x3a, 0x7f, 0xca, 0xd8, 0x45, 0x9a, 0xdd, 0xeb, 0xa7, 0xb7, 0xdb, 0x7f, 0x47, 0x5e, + 0xc8, 0x24, 0x5e, 0x42, 0x70, 0x18, 0xb4, 0x05, 0x32, 0xcb, 0x69, 0xaf, 0x78, 0xb7, 0xde, 0xd9, + 0x64, 0x46, 0xc9, 0x74, 0x46, 0xc9, 0xeb, 0x8c, 0x92, 0x9b, 0x39, 0x75, 0xa6, 0x73, 0xea, 0x3c, + 0xcf, 0xa9, 0x73, 0xde, 0x4d, 0x84, 0x19, 0xe4, 0x91, 0x1f, 0x63, 0xfa, 0x23, 0xf7, 0x6a, 0x89, + 0x6c, 0xc6, 0x0a, 0x74, 0x54, 0x2b, 0xbf, 0xa3, 0xf3, 0x11, 0x00, 0x00, 0xff, 0xff, 0x9b, 0x87, + 0xdc, 0x4b, 0x7c, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Parameters queries the parameters of the module. + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/pulsarchain.votepersistence.v1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Parameters queries the parameters of the module. + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pulsarchain.votepersistence.v1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var Query_serviceDesc = _Query_serviceDesc +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pulsarchain.votepersistence.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "pulsarchain/votepersistence/v1/query.proto", +} + +func (m *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/votepersistence/types/query.pb.gw.go b/x/votepersistence/types/query.pb.gw.go new file mode 100644 index 00000000..699c42c3 --- /dev/null +++ b/x/votepersistence/types/query.pb.gw.go @@ -0,0 +1,153 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: pulsarchain/votepersistence/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"node101-io", "pulsar-chain", "votepersistence", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage +) diff --git a/x/votepersistence/types/tx.pb.go b/x/votepersistence/types/tx.pb.go new file mode 100644 index 00000000..c72264a0 --- /dev/null +++ b/x/votepersistence/types/tx.pb.go @@ -0,0 +1,604 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/votepersistence/v1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgUpdateParams is the Msg/UpdateParams request type. +type MsgUpdateParams struct { + // authority is the address that controls the module (defaults to x/gov unless overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // params defines the module parameters to update. + // + // NOTE: All parameters must be supplied. + Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` +} + +func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } +func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParams) ProtoMessage() {} +func (*MsgUpdateParams) Descriptor() ([]byte, []int) { + return fileDescriptor_9ef0cb0ba71ad1b3, []int{0} +} +func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParams.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 *MsgUpdateParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParams.Merge(m, src) +} +func (m *MsgUpdateParams) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParams) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo + +func (m *MsgUpdateParams) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgUpdateParams) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// MsgUpdateParamsResponse defines the response structure for executing a +// MsgUpdateParams message. +type MsgUpdateParamsResponse struct { +} + +func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } +func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParamsResponse) ProtoMessage() {} +func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9ef0cb0ba71ad1b3, []int{1} +} +func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParamsResponse.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 *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) +} +func (m *MsgUpdateParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgUpdateParams)(nil), "pulsarchain.votepersistence.v1.MsgUpdateParams") + proto.RegisterType((*MsgUpdateParamsResponse)(nil), "pulsarchain.votepersistence.v1.MsgUpdateParamsResponse") +} + +func init() { + proto.RegisterFile("pulsarchain/votepersistence/v1/tx.proto", fileDescriptor_9ef0cb0ba71ad1b3) +} + +var fileDescriptor_9ef0cb0ba71ad1b3 = []byte{ + // 369 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2f, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x2f, 0xcb, 0x2f, 0x49, 0x2d, 0x48, 0x2d, 0x2a, + 0xce, 0x2c, 0x2e, 0x49, 0xcd, 0x4b, 0x4e, 0xd5, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, + 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x43, 0x52, 0xa8, 0x87, 0xa6, 0x50, 0xaf, 0xcc, 0x50, 0x4a, 0x30, + 0x31, 0x37, 0x33, 0x2f, 0x5f, 0x1f, 0x4c, 0x42, 0xb4, 0x48, 0x89, 0x27, 0xe7, 0x17, 0xe7, 0xe6, + 0x17, 0xeb, 0xe7, 0x16, 0xa7, 0x83, 0x8c, 0xca, 0x2d, 0x4e, 0x87, 0x4a, 0x48, 0x42, 0x24, 0xe2, + 0xc1, 0x3c, 0x7d, 0x08, 0x07, 0x2a, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x11, 0x07, 0xb1, 0xa0, + 0xa2, 0xda, 0x04, 0x5c, 0x59, 0x90, 0x58, 0x94, 0x98, 0x0b, 0x35, 0x42, 0xe9, 0x1a, 0x23, 0x17, + 0xbf, 0x6f, 0x71, 0x7a, 0x68, 0x41, 0x4a, 0x62, 0x49, 0x6a, 0x00, 0x58, 0x46, 0xc8, 0x8c, 0x8b, + 0x33, 0xb1, 0xb4, 0x24, 0x23, 0xbf, 0x28, 0xb3, 0xa4, 0x52, 0x82, 0x51, 0x81, 0x51, 0x83, 0xd3, + 0x49, 0xe2, 0xd2, 0x16, 0x5d, 0x11, 0xa8, 0xdd, 0x8e, 0x29, 0x29, 0x45, 0xa9, 0xc5, 0xc5, 0xc1, + 0x25, 0x45, 0x99, 0x79, 0xe9, 0x41, 0x08, 0xa5, 0x42, 0x9e, 0x5c, 0x6c, 0x10, 0xb3, 0x25, 0x98, + 0x14, 0x18, 0x35, 0xb8, 0x8d, 0xd4, 0xf4, 0xf0, 0x07, 0x83, 0x1e, 0xc4, 0x3e, 0x27, 0xce, 0x13, + 0xf7, 0xe4, 0x19, 0x56, 0x3c, 0xdf, 0xa0, 0xc5, 0x18, 0x04, 0x35, 0xc0, 0xca, 0xa1, 0xe9, 0xf9, + 0x06, 0x2d, 0x84, 0xd1, 0x5d, 0xcf, 0x37, 0x68, 0xe9, 0x22, 0x7b, 0xab, 0x02, 0xc3, 0x63, 0x68, + 0x9e, 0x50, 0x92, 0xe4, 0x12, 0x47, 0x13, 0x0a, 0x4a, 0x2d, 0x2e, 0xc8, 0xcf, 0x2b, 0x4e, 0x35, + 0x6a, 0x63, 0xe4, 0x62, 0xf6, 0x2d, 0x4e, 0x17, 0xaa, 0xe0, 0xe2, 0x41, 0xf1, 0xb7, 0x3e, 0x21, + 0xf7, 0xa2, 0x19, 0x28, 0x65, 0x4e, 0xa2, 0x06, 0x98, 0x0b, 0xa4, 0x58, 0x1b, 0x40, 0xbe, 0x75, + 0x0a, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, + 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xab, 0xf4, 0xcc, 0x92, + 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xbc, 0xfc, 0x94, 0x54, 0x43, 0x03, 0x43, 0xdd, + 0xcc, 0x7c, 0x7d, 0x88, 0x75, 0xba, 0xb8, 0xc2, 0xa0, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, + 0x1c, 0xb3, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xde, 0x4f, 0x5a, 0xaa, 0xae, 0x02, 0x00, + 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // UpdateParams defines a (governance) operation for updating the module + // parameters. The authority defaults to the x/gov module account. + UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/pulsarchain.votepersistence.v1.Msg/UpdateParams", 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 + // parameters. The authority defaults to the x/gov module account. + UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pulsarchain.votepersistence.v1.Msg/UpdateParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + } + return interceptor(ctx, in, info, handler) +} + +var Msg_serviceDesc = _Msg_serviceDesc +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pulsarchain.votepersistence.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "UpdateParams", + Handler: _Msg_UpdateParams_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "pulsarchain/votepersistence/v1/tx.proto", +} + +func (m *MsgUpdateParams) 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 *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParamsResponse) 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 *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgUpdateParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Params.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgUpdateParams) 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: MsgUpdateParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", 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.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParamsResponse) 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: MsgUpdateParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/votepersistence/types/types.go b/x/votepersistence/types/types.go new file mode 100644 index 00000000..ab1254f4 --- /dev/null +++ b/x/votepersistence/types/types.go @@ -0,0 +1 @@ +package types From a2e2e29002843c1f24d51b76910af5353c39fd15 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 27 Apr 2026 19:16:17 +0300 Subject: [PATCH 07/63] feat: add a collection map to store vote extensions --- x/votepersistence/keeper/keeper.go | 27 +++++++++++++++++++++++++++ x/votepersistence/types/keys.go | 2 ++ 2 files changed, 29 insertions(+) diff --git a/x/votepersistence/keeper/keeper.go b/x/votepersistence/keeper/keeper.go index ea31ae1c..da33720c 100644 --- a/x/votepersistence/keeper/keeper.go +++ b/x/votepersistence/keeper/keeper.go @@ -1,6 +1,7 @@ package keeper import ( + "context" "fmt" "cosmossdk.io/collections" @@ -11,6 +12,8 @@ import ( "github.com/node101-io/pulsar-chain/x/votepersistence/types" ) +const VoteStorageMapName string = "vote_storage" + type Keeper struct { storeService corestore.KVStoreService cdc codec.Codec @@ -19,6 +22,8 @@ type Keeper struct { // Typically, this should be the x/gov module account. authority []byte + voteStorage collections.Map[collections.Pair[int64, []byte], []byte] + Schema collections.Schema Params collections.Item[types.Params] } @@ -43,6 +48,12 @@ func NewKeeper( authority: authority, Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), + + voteStorage: collections.NewMap(sb, + types.VoteStorageMapPrefix, + VoteStorageMapName, + collections.PairKeyCodec(collections.Int64Key, collections.BytesKey), + collections.BytesValue), } schema, err := sb.Build() @@ -58,3 +69,19 @@ func NewKeeper( func (k Keeper) GetAuthority() []byte { return k.authority } + +func (k Keeper) SetVote(ctx context.Context, blockHeight int64, minaAddress, voteExtensions []byte) error { + return k.voteStorage.Set(ctx, collections.Join(blockHeight, minaAddress), voteExtensions) +} +func (k Keeper) GetVote(ctx context.Context, blockHeight int64, minaAddress []byte) ([]byte, error) { + return k.voteStorage.Get(ctx, collections.Join(blockHeight, minaAddress)) +} +func (k Keeper) RemoveVote(ctx context.Context, blockHeight int64, minaAddress []byte) error { + return k.voteStorage.Remove(ctx, collections.Join(blockHeight, minaAddress)) +} +func (k Keeper) VoteExists(ctx context.Context, blockHeight int64, minaAddress []byte) (bool, error) { + return k.voteStorage.Has(ctx, collections.Join(blockHeight, minaAddress)) +} +func (k Keeper) IterateVotes(ctx context.Context) (collections.Iterator[collections.Pair[int64, []byte], []byte], error) { + return k.voteStorage.Iterate(ctx, nil) +} diff --git a/x/votepersistence/types/keys.go b/x/votepersistence/types/keys.go index 08def311..312cef67 100644 --- a/x/votepersistence/types/keys.go +++ b/x/votepersistence/types/keys.go @@ -17,3 +17,5 @@ const ( // ParamsKey is the prefix to retrieve all Params var ParamsKey = collections.NewPrefix("p_votepersistence") + +var VoteStorageMapPrefix = collections.NewPrefix("vote_storage_map") From a8d183105b8ae0e20249ba8e0b42f212cd8abf06 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 27 Apr 2026 19:51:38 +0300 Subject: [PATCH 08/63] refactor: remove local vote map and get votes from cometbft --- abci/helpers.go | 23 ----------------------- abci/process_proposal.go | 18 +++++++++++++----- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/abci/helpers.go b/abci/helpers.go index 5edc9a33..a16ffd21 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -19,7 +19,6 @@ type AbciHandler struct { secondaryKey SecondaryKey stakingKeeper stakingkeeper.Keeper keyregistryKeeper keyregistrykeeper.Keeper - votes map[uint64]map[string][]byte // height -> minaAddress -> extension bytes } type VoteExtensionBody struct { @@ -40,25 +39,3 @@ func NewVoteExtHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Ke keyregistryKeeper: keyregistryKeeper, } } - -func (h *AbciHandler) storeVote(height uint64, minaKey string, voteExt []byte) { - - voteMap := h.votes[height] - - voteMap[minaKey] = voteExt - -} - -func (h *AbciHandler) fetchVote(height uint64, minaKey string) []byte { - - voteMap := h.votes[height] - - return voteMap[minaKey] -} - -func (h *AbciHandler) fetchVotes(height uint64) map[string][]byte { - - voteMap := h.votes[height] - - return voteMap -} diff --git a/abci/process_proposal.go b/abci/process_proposal.go index 4f9a6061..e252b64c 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -47,16 +47,24 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { var signedStakePower int64 var currentValidatorStakePower int64 - voteExtMap := h.fetchVotes(uint64(req.GetHeight()) - 2) + votes := req.ProposedLastCommit.Votes + valInfoMap := make(map[string]validatorInfo) + + // Require at least 2/3 signed power to prevent proposer-side signature withholding. for _, val := range valInfo { - if voteExtMap[string(val.ConsensusAddr)] != nil { - signedStakePower += val.Power - } + valInfoMap[string(val.ConsensusAddr)] = val currentValidatorStakePower += val.Power } - if signedStakePower*3 >= currentValidatorStakePower*2 { + for _, vote := range votes { + _, ok := valInfoMap[string(vote.Validator.Address)] + if ok { + signedStakePower += vote.Validator.Power + } + } + + if signedStakePower*3 < currentValidatorStakePower*2 { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil } From 4e1727062d4f2dc7322244b18225e7d94885843e Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 13:31:43 +0300 Subject: [PATCH 09/63] refactor: move functions to helpers and make vote extension compatible with spec --- abci/extend_vote.go | 114 ++------------- abci/helpers.go | 293 ++++++++++++++++++++++++++++++++++++--- abci/prepare_proposal.go | 38 ++--- abci/process_proposal.go | 49 +------ abci/verify_vote_ext.go | 27 ++-- 5 files changed, 309 insertions(+), 212 deletions(-) diff --git a/abci/extend_vote.go b/abci/extend_vote.go index c5e04b6b..d3abfcde 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -1,15 +1,10 @@ package vote_ext import ( - "math/big" - abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - "github.com/node101-io/mina-signer-go/constants" - "github.com/node101-io/mina-signer-go/field" - "github.com/node101-io/mina-signer-go/keys" - "github.com/node101-io/mina-signer-go/poseidon" + keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" ) const ActionsReducedRoot string = "pulsar" @@ -19,86 +14,16 @@ type validatorInfo struct { Power int64 } -func MockSign(voteExtBody VoteExtensionBody) []byte { - return []byte{} -} - -func MockSignatureVerify(voteExtBody VoteExtensionBody, minaKey []byte, reducedRoot string) bool { - return true +type VoteExtensionBody struct { + NextValidatorSetHash []byte + CurrentStateRoot []byte + CurrentBlockHeight int64 } -func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]validatorInfo, error) { - - historicalData, err := h.stakingKeeper.GetHistoricalInfo(ctx, currentBlockHeight) - if err != nil { - return nil, err - } - - validatorSet := historicalData.Valset - - var valInfo []validatorInfo - - for _, validator := range validatorSet { - - consAddr, err := validator.GetConsAddr() - if err != nil { - return nil, err - } - - consPower := validator.ConsensusPower(sdk.DefaultPowerReduction) - - valInfo = append(valInfo, validatorInfo{ - ConsensusAddr: consAddr, - Power: consPower, - }) - } - return valInfo, nil -} - -func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []validatorInfo, poseidonHash *poseidon.Poseidon) (*big.Int, error) { - - input := []*big.Int{big.NewInt(0)} - merkleRoot := poseidonHash.Hash(input) - - for _, validator := range valInfo { - input = []*big.Int{} - - minaPubKeyExists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, validator.ConsensusAddr) - if err != nil { - return nil, err - } - if !minaPubKeyExists { - return nil, err - } - - minaPubKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, validator.ConsensusAddr) - if err != nil { - return nil, err - } - - MinaPublicKey, err := keys.PublicKey{}.FromAddress(string(minaPubKey)) - if err != nil { - return nil, err - } - - input = append(input, MinaPublicKey.X) - if MinaPublicKey.IsOdd { - input = append(input, big.NewInt(1)) - } else { - input = append(input, big.NewInt(0)) - } - power := new(big.Int).SetInt64(validator.Power) - input = append(input, power) - - hashOfAddr := poseidonHash.Hash(input) - - input = []*big.Int{merkleRoot, hashOfAddr} - - merkleRoot = poseidonHash.Hash(input) - } - - return merkleRoot, nil - +type AbciHandler struct { + secondaryKey SecondaryKey + stakingKeeper stakingkeeper.Keeper + keyregistryKeeper keyregistrykeeper.Keeper } func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { @@ -107,30 +32,11 @@ func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return &abci.ResponseExtendVote{VoteExtension: []byte{}}, nil } - twoBlocksBefore, err := stakingkeeper.Keeper.GetHistoricalInfo(h.stakingKeeper, ctx, req.GetHeight()-2) - if err != nil { - return &abci.ResponseExtendVote{VoteExtension: []byte{}}, err - } - - nextBlockHeight := req.GetHeight() - 1 - - poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) - - nextValSet, err := h.getValidatorSet(ctx, nextBlockHeight) - if err != nil { - return nil, err - } - nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, nextValSet, poseidonHash) + body, err := h.constructVoteExtBody(ctx, req.GetHeight()) if err != nil { return nil, err } - body := VoteExtensionBody{ - NextBlockHeight: nextBlockHeight, - CurrentStateRoot: twoBlocksBefore.Header.AppHash, - NextValidatorSetHash: nextValidatorSetHash.Bytes(), - } - bz := MockSign(body) return &abci.ResponseExtendVote{VoteExtension: bz}, nil diff --git a/abci/helpers.go b/abci/helpers.go index a16ffd21..c11ee04e 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -1,41 +1,294 @@ package vote_ext import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "strings" + + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/node101-io/mina-signer-go/constants" + "github.com/node101-io/mina-signer-go/field" "github.com/node101-io/mina-signer-go/keys" + "github.com/node101-io/mina-signer-go/poseidon" keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" ) -var VoteExtMarker []byte = []byte("VOTEEXT:") - -const AcceptanceRatio float64 = 0.66 - type SecondaryKey struct { SecretKey *keys.PrivateKey PublicKey *keys.PublicKey } -type AbciHandler struct { - secondaryKey SecondaryKey - stakingKeeper stakingkeeper.Keeper - keyregistryKeeper keyregistrykeeper.Keeper +func NewVoteExtHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Keeper, keyregistryKeeper keyregistrykeeper.Keeper) *AbciHandler { + return &AbciHandler{ + secondaryKey: secondaryKey, + stakingKeeper: stakingKeeper, + keyregistryKeeper: keyregistryKeeper, + } } -type VoteExtensionBody struct { - NextValidatorSetHash []byte - CurrentStateRoot []byte - NextBlockHeight int64 +func MockSign(voteExtBody VoteExtensionBody) []byte { + return []byte{} } -type payload struct { - Height uint64 `json:"height"` - Votes map[string][]byte `json:"votes"` +func MockSignatureVerify(signature []byte, message VoteExtensionBody, minaKey []byte, reducedRoot string) bool { + return true } -func NewVoteExtHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Keeper, keyregistryKeeper keyregistrykeeper.Keeper) *AbciHandler { - return &AbciHandler{ - secondaryKey: secondaryKey, - stakingKeeper: stakingKeeper, - keyregistryKeeper: keyregistryKeeper, +func (h *AbciHandler) verifyVoteExtension(ctx context.Context, txs [][]byte, body VoteExtensionBody) error { + + voteExtensionTx := txs[0] + + if !strings.Contains(string(txs[0]), VoteExtMarker) { + return fmt.Errorf("") + } + + voteExtensionTx = voteExtensionTx[len([]byte(VoteExtMarker)):] + + var payload payload + + err := json.Unmarshal(voteExtensionTx, &payload) + if err != nil { + return err + } + + for publicKey, vote := range payload.Votes { + + pk, err := hex.DecodeString(publicKey) + if err != nil { + return err + } + + exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, pk) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("") + } + + minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, pk) + if err != nil { + return err + } + + if !MockSignatureVerify(vote, body, minaKey, ActionsReducedRoot) { + return fmt.Errorf("") + } + + } + + return nil +} + +func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]validatorInfo, error) { + + historicalData, err := h.stakingKeeper.GetHistoricalInfo(ctx, currentBlockHeight) + if err != nil { + return nil, err + } + + validatorSet := historicalData.Valset + + var valInfo []validatorInfo + + for _, validator := range validatorSet { + + consAddr, err := validator.GetConsAddr() + if err != nil { + return nil, err + } + + consPower := validator.ConsensusPower(sdk.DefaultPowerReduction) + + valInfo = append(valInfo, validatorInfo{ + ConsensusAddr: consAddr, + Power: consPower, + }) } + return valInfo, nil +} + +// TODO: Move this helper to mina-signer-go +func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []validatorInfo, poseidonHash *poseidon.Poseidon) (*big.Int, error) { + + input := []*big.Int{big.NewInt(0)} + merkleRoot := poseidonHash.Hash(input) + + for _, validator := range valInfo { + input = []*big.Int{} + + cosmosValidatorInfo, err := h.stakingKeeper.Validator(ctx, validator.ConsensusAddr) + if err != nil { + return nil, err + } + + cosmosValidatorPubKey, err := cosmosValidatorInfo.ConsPubKey() + if err != nil { + return nil, err + } + + minaPubKeyExists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, cosmosValidatorPubKey.Bytes()) + if err != nil { + return nil, err + } + if !minaPubKeyExists { + return nil, err + } + + minaPubKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, cosmosValidatorPubKey.Bytes()) + if err != nil { + return nil, err + } + + MinaPublicKey, err := keys.PublicKey{}.FromAddress(string(minaPubKey)) + if err != nil { + return nil, err + } + + input = append(input, MinaPublicKey.X) + if MinaPublicKey.IsOdd { + input = append(input, big.NewInt(1)) + } else { + input = append(input, big.NewInt(0)) + } + power := new(big.Int).SetInt64(validator.Power) + input = append(input, power) + + hashOfAddr := poseidonHash.Hash(input) + + input = []*big.Int{merkleRoot, hashOfAddr} + + merkleRoot = poseidonHash.Hash(input) + } + + return merkleRoot, nil + +} + +func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, txs [][]byte) (bool, error) { + var signedStakePower int64 + var currentValidatorStakePower int64 + + valInfoMap := make(map[string]validatorInfo) + + currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) + if err != nil { + return false, err + } + + // Require at least 2/3 signed power to prevent proposer-side signature withholding. + for _, val := range currentValidatorSet { + + cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, val.ConsensusAddr) + if err != nil { + return false, err + } + + valInfoMap[hex.EncodeToString(cosmosValidatorPubKey)] = val + currentValidatorStakePower += val.Power + } + + voteExtensionTx := txs[0] + + voteExtensionTx = voteExtensionTx[len([]byte(VoteExtMarker)):] + + var payload payload + + err = json.Unmarshal(voteExtensionTx, &payload) + if err != nil { + return false, err + } + + for addr := range payload.Votes { + validatorInfo, ok := valInfoMap[addr] + if ok { + signedStakePower += validatorInfo.Power + } + } + if signedStakePower*3 < currentValidatorStakePower*2 { + return false, nil + } + + return true, nil +} + +func (h *AbciHandler) constructVoteExtBody(ctx sdk.Context, blockHeight int64) (VoteExtensionBody, error) { + + nextValidatorSet, err := h.getValidatorSet(ctx, blockHeight) + if err != nil { + return VoteExtensionBody{}, err + } + + currentBlockInfo, err := h.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-1) + if err != nil { + return VoteExtensionBody{}, err + } + + poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) + + nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, nextValidatorSet, poseidonHash) + if err != nil { + return VoteExtensionBody{}, err + } + if nextValidatorSetHash == nil { + return VoteExtensionBody{}, err + } + + return VoteExtensionBody{ + NextValidatorSetHash: nextValidatorSetHash.Bytes(), + CurrentStateRoot: currentBlockInfo.Header.AppHash, + CurrentBlockHeight: blockHeight - 1, + }, nil +} + +func (h *AbciHandler) getValidatorPublicKey(ctx sdk.Context, validatorAddr []byte) ([]byte, error) { + cosmosValidatorInfo, err := h.stakingKeeper.Validator(ctx, validatorAddr) + if err != nil { + return nil, err + } + cosmosValidatorPubKey, err := cosmosValidatorInfo.ConsPubKey() + if err != nil { + return nil, err + } + + return cosmosValidatorPubKey.Bytes(), nil +} + +func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteExtensions []abci.ExtendedVoteInfo) (payload, error) { + voteExtsForGivenBlock := make(map[string][]byte) + currentValidatorSetMap := make(map[string]bool) + + currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) + if err != nil { + return payload{}, err + } + + for _, currentValidator := range currentValidatorSet { + currentValidatorSetMap[string(currentValidator.ConsensusAddr)] = true + } + + for i, vote := range voteExtensions { + + if !currentValidatorSetMap[string(vote.Validator.Address)] { + continue + } + + cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, vote.Validator.Address) + if err != nil { + return payload{}, err + } + + voteExtsForGivenBlock[hex.EncodeToString(cosmosValidatorPubKey)] = voteExtensions[i].VoteExtension + } + + if len(voteExtsForGivenBlock) == 0 { + return payload{}, nil + } + + return payload{Height: blockHeight - 1, Votes: voteExtsForGivenBlock}, nil } diff --git a/abci/prepare_proposal.go b/abci/prepare_proposal.go index a5b34ec4..feaa7116 100644 --- a/abci/prepare_proposal.go +++ b/abci/prepare_proposal.go @@ -2,51 +2,35 @@ package vote_ext import ( "encoding/json" - "fmt" abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" ) +var VoteExtMarker string = "VOTEEXT:" + +type payload struct { + Height int64 `json:"height"` + Votes map[string][]byte `json:"votes"` +} + func (h *AbciHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) { - voteExtsForGivenBlock := make(map[string][]byte) - targetHeight := uint64(req.GetHeight() - 1) - - valInfo, err := h.getValidatorSet(ctx, req.Height) + votes := req.LocalLastCommit.Votes + pl, err := h.constructPayload(ctx, req.GetHeight(), votes) if err != nil { return &abci.ResponsePrepareProposal{Txs: req.Txs}, err } - for i, val := range valInfo { - - exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, val.ConsensusAddr) - if err != nil { - return &abci.ResponsePrepareProposal{Txs: req.Txs}, err - } - if !exists { - return &abci.ResponsePrepareProposal{Txs: req.Txs}, err - } - - votes := req.LocalLastCommit.Votes - - voteExtsForGivenBlock[string(votes[i].Validator.Address)] = votes[i].ExtensionSignature - } - - if len(voteExtsForGivenBlock) == 0 { - return &abci.ResponsePrepareProposal{Txs: req.Txs}, err - } - - pl := payload{Height: targetHeight, Votes: voteExtsForGivenBlock} bz, err := json.Marshal(pl) if err != nil { - return nil, fmt.Errorf("") + return nil, err } // prefix makes it easier to identify the vote extension - extTx := append(VoteExtMarker, bz...) + extTx := append([]byte(VoteExtMarker), bz...) // prepend to existing txs txs := make([][]byte, 0, len(req.Txs)+1) diff --git a/abci/process_proposal.go b/abci/process_proposal.go index e252b64c..83d15ab1 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -1,12 +1,10 @@ package vote_ext import ( + "fmt" + abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - "github.com/node101-io/mina-signer-go/constants" - "github.com/node101-io/mina-signer-go/field" - "github.com/node101-io/mina-signer-go/poseidon" ) func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { @@ -18,58 +16,25 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil } - // vote ext reconstruct - currentState, err := stakingkeeper.Keeper.GetHistoricalInfo(h.stakingKeeper, ctx, req.GetHeight()-2) + body, err := h.constructVoteExtBody(ctx, req.GetHeight()-1) if err != nil { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } - valInfo, err := h.getValidatorSet(ctx, req.GetHeight()-1) + err = h.verifyVoteExtension(ctx, req.Txs, body) if err != nil { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } - poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) - - nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, valInfo, poseidonHash) + isEnoughStakePower, err := h.checkStakePower(ctx, req.GetHeight(), req.Txs) if err != nil { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } - if nextValidatorSetHash == nil { - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err - } - body := VoteExtensionBody{ - NextBlockHeight: req.GetHeight() - 1, - CurrentStateRoot: currentState.Header.AppHash, - NextValidatorSetHash: nextValidatorSetHash.Bytes(), + if !isEnoughStakePower { + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, fmt.Errorf("") } - var signedStakePower int64 - var currentValidatorStakePower int64 - - votes := req.ProposedLastCommit.Votes - valInfoMap := make(map[string]validatorInfo) - - // Require at least 2/3 signed power to prevent proposer-side signature withholding. - for _, val := range valInfo { - valInfoMap[string(val.ConsensusAddr)] = val - currentValidatorStakePower += val.Power - } - - for _, vote := range votes { - _, ok := valInfoMap[string(vote.Validator.Address)] - if ok { - signedStakePower += vote.Validator.Power - } - } - - if signedStakePower*3 < currentValidatorStakePower*2 { - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil - } - - MockSignatureVerify(body, h.secondaryKey.PublicKey.X.Bytes(), ActionsReducedRoot) - // Vote extension successfully verified return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil } diff --git a/abci/verify_vote_ext.go b/abci/verify_vote_ext.go index 18eeb14e..167f3334 100644 --- a/abci/verify_vote_ext.go +++ b/abci/verify_vote_ext.go @@ -5,9 +5,6 @@ import ( abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/node101-io/mina-signer-go/constants" - "github.com/node101-io/mina-signer-go/field" - "github.com/node101-io/mina-signer-go/poseidon" ) func (h *AbciHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandler { @@ -20,39 +17,31 @@ func (h *AbciHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandle return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, fmt.Errorf("rejected") } - cosmosValAddr := req.GetValidatorAddress() - - exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, cosmosValAddr) + cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, req.ValidatorAddress) if err != nil { return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err } - if !exists { + + exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, cosmosValidatorPubKey) + if err != nil { return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err } - poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) - - minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, cosmosValAddr) - if err != nil { + if !exists { return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err } - valInfo, err := h.getValidatorSet(ctx, req.Height) + minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, cosmosValidatorPubKey) if err != nil { return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err } - setRoot, err := h.calculateValidatorSetRoot(ctx, valInfo, poseidonHash) + body, err := h.constructVoteExtBody(ctx, req.GetHeight()) if err != nil { return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err } - sigValidity := MockSignatureVerify(VoteExtensionBody{ - NextValidatorSetHash: setRoot.Bytes(), - CurrentStateRoot: ctx.HeaderInfo().AppHash, - NextBlockHeight: req.Height, - }, minaKey, ActionsReducedRoot) - + sigValidity := MockSignatureVerify(req.VoteExtension, body, minaKey, ActionsReducedRoot) if !sigValidity { return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err } From 32c0209c338efd5b9ac1a89705b27c4c90c53184 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 19:41:05 +0300 Subject: [PATCH 10/63] fix: prepare/process proposals with blocks < 3 to remove the empty vote extension error --- abci/extend_vote.go | 1 + abci/prepare_proposal.go | 6 ++++++ abci/process_proposal.go | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/abci/extend_vote.go b/abci/extend_vote.go index d3abfcde..65bbcf54 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -28,6 +28,7 @@ type AbciHandler struct { func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return func(ctx sdk.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) { + if req.GetHeight() < 3 { return &abci.ResponseExtendVote{VoteExtension: []byte{}}, nil } diff --git a/abci/prepare_proposal.go b/abci/prepare_proposal.go index feaa7116..aa6f85ee 100644 --- a/abci/prepare_proposal.go +++ b/abci/prepare_proposal.go @@ -18,6 +18,12 @@ func (h *AbciHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) { + // to construct the payload we need to get the N-2th block's vote extensions. + // Hence, enabling prepare proposal on blocks < 3 will result in error. + if req.Height < 3 { + return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil + } + votes := req.LocalLastCommit.Votes pl, err := h.constructPayload(ctx, req.GetHeight(), votes) if err != nil { diff --git a/abci/process_proposal.go b/abci/process_proposal.go index 83d15ab1..c3184ea6 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -11,8 +11,8 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return func(ctx sdk.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) { - // If height is 1, we won't have any votes thus skip the proposal - if req.GetHeight() == 1 { + // If height is less than 3, we won't have any votes thus skip the proposal + if req.GetHeight() < 3 { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil } From 8407d989bf0fbafb6a4e4868957bbeb230f09910 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 19:41:34 +0300 Subject: [PATCH 11/63] feat: enable vote extensions --- app/app.go | 42 ++++++++++++++++++++++++++++++++++++++++++ config.yml | 2 ++ 2 files changed, 44 insertions(+) diff --git a/app/app.go b/app/app.go index f0f85bd8..6d6d0470 100644 --- a/app/app.go +++ b/app/app.go @@ -1,7 +1,10 @@ package app import ( + "encoding/base64" + "fmt" "io" + "math/big" clienthelpers "cosmossdk.io/client/v2/helpers" "cosmossdk.io/core/appmodule" @@ -45,6 +48,8 @@ import ( ibctransferkeeper "github.com/cosmos/ibc-go/v10/modules/apps/transfer/keeper" ibckeeper "github.com/cosmos/ibc-go/v10/modules/core/keeper" + "github.com/node101-io/mina-signer-go/keys" + vote_ext "github.com/node101-io/pulsar-chain/abci" "github.com/node101-io/pulsar-chain/docs" keyregistrymodulekeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" pulsarmodulekeeper "github.com/node101-io/pulsar-chain/x/pulsar/keeper" @@ -105,6 +110,8 @@ type App struct { PulsarKeeper pulsarmodulekeeper.Keeper KeyregistryKeeper keyregistrymodulekeeper.Keeper VotepersistenceKeeper votepersistencemodulekeeper.Keeper + + AbciHandler *vote_ext.AbciHandler } func init() { @@ -191,6 +198,35 @@ func New( panic(err) } + minaPrivKey := appOpts.Get("vote_extension.priv_key") + keyStr, ok := minaPrivKey.(string) + if !ok { + panic("vote_extension.priv_key is not a string") + } + + // Decode base64 -> bytes + keyBytes, err := base64.StdEncoding.DecodeString(keyStr) + if err != nil { + panic(fmt.Sprintf("failed to decode base64 priv key: %v", err)) + } + + // Bytes -> big.Int + prv := new(big.Int).SetBytes(keyBytes) + priv := keys.PrivateKey{ + Value: prv, + } + public := priv.ToPublicKey() + secondaryKey := vote_ext.SecondaryKey{ + SecretKey: &priv, + PublicKey: &public, + } + + app.AbciHandler = vote_ext.NewVoteExtHandler( + secondaryKey, + *app.StakingKeeper, + app.KeyregistryKeeper, + ) + // add to default baseapp options // enable optimistic execution baseAppOptions = append(baseAppOptions, baseapp.SetOptimisticExecution()) @@ -198,6 +234,12 @@ func New( // build app app.App = appBuilder.Build(db, traceStore, baseAppOptions...) + app.SetExtendVoteHandler(app.AbciHandler.ExtendVoteHandler()) + app.SetVerifyVoteExtensionHandler(app.AbciHandler.VerifyVoteExtensionHandler()) + app.SetPrepareProposal(app.AbciHandler.PrepareProposalHandler()) + app.SetProcessProposal(app.AbciHandler.ProcessProposalHandler()) + app.SetPreBlocker(app.AbciHandler.PreBlocker()) + // register legacy modules if err := app.registerIBCModules(appOpts); err != nil { panic(err) diff --git a/config.yml b/config.yml index afd3dd7e..8cf152d8 100644 --- a/config.yml +++ b/config.yml @@ -29,6 +29,8 @@ validators: - name: validator2 bonded: 100000000pmina + + genesis: app_state: keyregistry: From 07488b40f17b673d233ed1bb7f04619d13a9f752 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 19:46:21 +0300 Subject: [PATCH 12/63] test: add tests for vote extension storage map --- x/votepersistence/keeper/vote_storage_test.go | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 x/votepersistence/keeper/vote_storage_test.go diff --git a/x/votepersistence/keeper/vote_storage_test.go b/x/votepersistence/keeper/vote_storage_test.go new file mode 100644 index 00000000..6b04daba --- /dev/null +++ b/x/votepersistence/keeper/vote_storage_test.go @@ -0,0 +1,114 @@ +package keeper_test + +import ( + "bytes" + "testing" + + "cosmossdk.io/collections" + "github.com/stretchr/testify/require" +) + +type voteEntry struct { + blockHeight int64 + minaAddress []byte + voteExtensions []byte +} + +func TestVoteStorageSetGetHas(t *testing.T) { + f := initFixture(t) + + blockHeight := int64(42) + minaAddress := []byte("mina-address-1") + voteExtensions := []byte("vote-extension-1") + + exists, err := f.keeper.VoteExists(f.ctx, blockHeight, minaAddress) + require.NoError(t, err) + require.False(t, exists) + + err = f.keeper.SetVote(f.ctx, blockHeight, minaAddress, voteExtensions) + require.NoError(t, err) + + got, err := f.keeper.GetVote(f.ctx, blockHeight, minaAddress) + require.NoError(t, err) + require.Equal(t, voteExtensions, got) + + exists, err = f.keeper.VoteExists(f.ctx, blockHeight, minaAddress) + require.NoError(t, err) + require.True(t, exists) +} + +func TestVoteStorageGetFailsWhenVoteMissing(t *testing.T) { + f := initFixture(t) + + _, err := f.keeper.GetVote(f.ctx, 42, []byte("missing-mina-address")) + require.ErrorIs(t, err, collections.ErrNotFound) +} + +func TestVoteStorageRemove(t *testing.T) { + f := initFixture(t) + + blockHeight := int64(42) + minaAddress := []byte("mina-address-1") + voteExtensions := []byte("vote-extension-1") + + err := f.keeper.SetVote(f.ctx, blockHeight, minaAddress, voteExtensions) + require.NoError(t, err) + + exists, err := f.keeper.VoteExists(f.ctx, blockHeight, minaAddress) + require.NoError(t, err) + require.True(t, exists) + + err = f.keeper.RemoveVote(f.ctx, blockHeight, minaAddress) + require.NoError(t, err) + + exists, err = f.keeper.VoteExists(f.ctx, blockHeight, minaAddress) + require.NoError(t, err) + require.False(t, exists) + + _, err = f.keeper.GetVote(f.ctx, blockHeight, minaAddress) + require.ErrorIs(t, err, collections.ErrNotFound) +} + +func TestVoteStorageIterate(t *testing.T) { + f := initFixture(t) + + entries := []voteEntry{ + {blockHeight: 8, minaAddress: []byte("mina-b"), voteExtensions: []byte("vote-b")}, + {blockHeight: 3, minaAddress: []byte("mina-c"), voteExtensions: []byte("vote-c")}, + {blockHeight: 3, minaAddress: []byte("mina-a"), voteExtensions: []byte("vote-a")}, + } + + for _, entry := range entries { + err := f.keeper.SetVote(f.ctx, entry.blockHeight, entry.minaAddress, entry.voteExtensions) + require.NoError(t, err) + } + + iter, err := f.keeper.IterateVotes(f.ctx) + require.NoError(t, err) + defer iter.Close() + + var got []voteEntry + for iter.Valid() { + key, err := iter.Key() + require.NoError(t, err) + + value, err := iter.Value() + require.NoError(t, err) + + got = append(got, voteEntry{ + blockHeight: key.K1(), + minaAddress: bytes.Clone(key.K2()), + voteExtensions: bytes.Clone(value), + }) + + iter.Next() + } + + expected := []voteEntry{ + {blockHeight: 3, minaAddress: []byte("mina-a"), voteExtensions: []byte("vote-a")}, + {blockHeight: 3, minaAddress: []byte("mina-c"), voteExtensions: []byte("vote-c")}, + {blockHeight: 8, minaAddress: []byte("mina-b"), voteExtensions: []byte("vote-b")}, + } + + require.Equal(t, expected, got) +} From 2d75de59743dc7519ca6452535cd0c60ca47b7b3 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 21:11:30 +0300 Subject: [PATCH 13/63] feat: add a function to allow removing all votes from the vote storage map --- x/votepersistence/keeper/keeper.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/x/votepersistence/keeper/keeper.go b/x/votepersistence/keeper/keeper.go index da33720c..1b43d965 100644 --- a/x/votepersistence/keeper/keeper.go +++ b/x/votepersistence/keeper/keeper.go @@ -79,6 +79,29 @@ func (k Keeper) GetVote(ctx context.Context, blockHeight int64, minaAddress []by func (k Keeper) RemoveVote(ctx context.Context, blockHeight int64, minaAddress []byte) error { return k.voteStorage.Remove(ctx, collections.Join(blockHeight, minaAddress)) } + +func (k Keeper) RemoveVotes(ctx context.Context) error { + + iterator, err := k.voteStorage.Iterate(ctx, nil) + if err != nil { + return err + } + defer iterator.Close() + + for iterator.Valid() { + key, err := iterator.Key() + if err != nil { + return err + } + err = k.voteStorage.Remove(ctx, key) + if err != nil { + return err + } + iterator.Next() + } + return nil +} + func (k Keeper) VoteExists(ctx context.Context, blockHeight int64, minaAddress []byte) (bool, error) { return k.voteStorage.Has(ctx, collections.Join(blockHeight, minaAddress)) } From a6b6c3aa90a02951dc76dfc19f6ee04a3d8f18bb Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 21:14:14 +0300 Subject: [PATCH 14/63] feat: add a field to abci handler to use vote persistence module functionality --- abci/extend_vote.go | 8 +++++--- abci/helpers.go | 11 +++++++---- app/app.go | 1 + 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/abci/extend_vote.go b/abci/extend_vote.go index 65bbcf54..2cf27b64 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" + votepersistence "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" ) const ActionsReducedRoot string = "pulsar" @@ -21,9 +22,10 @@ type VoteExtensionBody struct { } type AbciHandler struct { - secondaryKey SecondaryKey - stakingKeeper stakingkeeper.Keeper - keyregistryKeeper keyregistrykeeper.Keeper + secondaryKey SecondaryKey + stakingKeeper stakingkeeper.Keeper + keyregistryKeeper keyregistrykeeper.Keeper + votePersistenceKeeper votepersistence.Keeper } func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { diff --git a/abci/helpers.go b/abci/helpers.go index c11ee04e..47a190c0 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -16,6 +16,7 @@ import ( "github.com/node101-io/mina-signer-go/keys" "github.com/node101-io/mina-signer-go/poseidon" keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" + votepersistence "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" ) type SecondaryKey struct { @@ -23,11 +24,13 @@ type SecondaryKey struct { PublicKey *keys.PublicKey } -func NewVoteExtHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Keeper, keyregistryKeeper keyregistrykeeper.Keeper) *AbciHandler { +func NewVoteExtHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Keeper, + keyregistryKeeper keyregistrykeeper.Keeper, votepersistenceKeeper votepersistence.Keeper) *AbciHandler { return &AbciHandler{ - secondaryKey: secondaryKey, - stakingKeeper: stakingKeeper, - keyregistryKeeper: keyregistryKeeper, + secondaryKey: secondaryKey, + stakingKeeper: stakingKeeper, + keyregistryKeeper: keyregistryKeeper, + votePersistenceKeeper: votepersistenceKeeper, } } diff --git a/app/app.go b/app/app.go index 6d6d0470..acc1ab20 100644 --- a/app/app.go +++ b/app/app.go @@ -225,6 +225,7 @@ func New( secondaryKey, *app.StakingKeeper, app.KeyregistryKeeper, + app.VotepersistenceKeeper, ) // add to default baseapp options From 5e3e2aaf73c41be644a34b814faa093307761597 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 21:14:33 +0300 Subject: [PATCH 15/63] feat: implement pre blocker --- abci/pre_blocker.go | 82 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 abci/pre_blocker.go diff --git a/abci/pre_blocker.go b/abci/pre_blocker.go new file mode 100644 index 00000000..31f31a88 --- /dev/null +++ b/abci/pre_blocker.go @@ -0,0 +1,82 @@ +package vote_ext + +import ( + "encoding/hex" + "encoding/json" + "fmt" + + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (h *AbciHandler) PreBlocker() sdk.PreBlocker { + return func(ctx sdk.Context, req *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) { + + // If height is smaller than 4, we won't have any votes thus skip the proposal + if req.GetHeight() < 3 { + return &sdk.ResponsePreBlock{}, nil + } + + err := h.votePersistenceKeeper.RemoveVotes(ctx) + if err != nil { + return nil, err + } + + voteExtensionTx := req.Txs[0] + + voteExtensionTx = voteExtensionTx[len([]byte(VoteExtMarker)):] + + var pl payload + + err = json.Unmarshal(voteExtensionTx, &pl) + if err != nil { + return nil, err + } + + currentValidatorSet, err := h.getValidatorSet(ctx, req.GetHeight()-2) + if err != nil { + return nil, err + } + + currentValidatorSetMap := make(map[string][]byte) + + for _, currentValidator := range currentValidatorSet { + cosmosValidatorPublicKey, err := h.getValidatorPublicKey(ctx, currentValidator.ConsensusAddr) + if err != nil { + return nil, err + } + + currentValidatorSetMap[hex.EncodeToString(cosmosValidatorPublicKey)] = cosmosValidatorPublicKey + } + + for addr, vote := range pl.Votes { + + cosmosValidatorPublicKey, ok := currentValidatorSetMap[addr] + if !ok { + continue + } + + exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, cosmosValidatorPublicKey) + if err != nil { + return nil, err + } + + if !exists { + return nil, fmt.Errorf("") + } + + minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, cosmosValidatorPublicKey) + if err != nil { + return nil, err + } + + err = h.votePersistenceKeeper.SetVote(ctx, req.GetHeight()-2, minaKey, vote) + if err != nil { + return nil, err + } + + } + + return &sdk.ResponsePreBlock{}, nil + } +} From 1fd854cce6065248bbc1a8f8a292fc3420b12e48 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 21:20:36 +0300 Subject: [PATCH 16/63] test: add a test for remove votes --- x/votepersistence/keeper/vote_storage_test.go | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/x/votepersistence/keeper/vote_storage_test.go b/x/votepersistence/keeper/vote_storage_test.go index 6b04daba..f3e9c2f2 100644 --- a/x/votepersistence/keeper/vote_storage_test.go +++ b/x/votepersistence/keeper/vote_storage_test.go @@ -69,6 +69,36 @@ func TestVoteStorageRemove(t *testing.T) { require.ErrorIs(t, err, collections.ErrNotFound) } +func TestVoteStorageRemoveVotes(t *testing.T) { + f := initFixture(t) + + entries := []voteEntry{ + {blockHeight: 3, minaAddress: []byte("mina-a"), voteExtensions: []byte("vote-a")}, + {blockHeight: 3, minaAddress: []byte("mina-b"), voteExtensions: []byte("vote-b")}, + {blockHeight: 8, minaAddress: []byte("mina-c"), voteExtensions: []byte("vote-c")}, + } + + for _, entry := range entries { + err := f.keeper.SetVote(f.ctx, entry.blockHeight, entry.minaAddress, entry.voteExtensions) + require.NoError(t, err) + } + + err := f.keeper.RemoveVotes(f.ctx) + require.NoError(t, err) + + for _, entry := range entries { + exists, err := f.keeper.VoteExists(f.ctx, entry.blockHeight, entry.minaAddress) + require.NoError(t, err) + require.False(t, exists) + } + + iter, err := f.keeper.IterateVotes(f.ctx) + require.NoError(t, err) + defer iter.Close() + + require.False(t, iter.Valid()) +} + func TestVoteStorageIterate(t *testing.T) { f := initFixture(t) From 0cb004154d940fdad2b5c64a3ea7b1061adfee93 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 21:34:12 +0300 Subject: [PATCH 17/63] feat: initialize query for vote extension payload --- .../votepersistence/v1/query.proto | 18 + x/pulsar/types/genesis.pb.go | 7 +- x/pulsar/types/module.pb.go | 5 +- x/pulsar/types/params.pb.go | 7 +- x/pulsar/types/query.pb.go | 7 +- x/pulsar/types/tx.pb.go | 7 +- .../keeper/query_vote_ext_body_by_height.go | 17 + x/votepersistence/module/autocli.go | 7 + x/votepersistence/types/genesis.pb.go | 7 +- x/votepersistence/types/module.pb.go | 5 +- x/votepersistence/types/params.pb.go | 7 +- x/votepersistence/types/query.pb.go | 519 +++++++++++++++++- x/votepersistence/types/query.pb.gw.go | 101 ++++ x/votepersistence/types/tx.pb.go | 7 +- 14 files changed, 660 insertions(+), 61 deletions(-) create mode 100644 x/votepersistence/keeper/query_vote_ext_body_by_height.go diff --git a/proto/pulsarchain/votepersistence/v1/query.proto b/proto/pulsarchain/votepersistence/v1/query.proto index aecc4d2d..6d8ce856 100644 --- a/proto/pulsarchain/votepersistence/v1/query.proto +++ b/proto/pulsarchain/votepersistence/v1/query.proto @@ -1,4 +1,5 @@ syntax = "proto3"; + package pulsarchain.votepersistence.v1; import "amino/amino.proto"; @@ -15,6 +16,11 @@ service Query { rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { option (google.api.http).get = "/node101-io/pulsar-chain/votepersistence/v1/params"; } + + // VoteExtBodyByHeight Queries a list of VoteExtBodyByHeight items. + rpc VoteExtBodyByHeight(QueryVoteExtBodyByHeightRequest) returns (QueryVoteExtBodyByHeightResponse) { + option (google.api.http).get = "/node101-io/pulsar-chain/votepersistence/v1/vote_ext_body_by_height/{block_height}"; + } } // QueryParamsRequest is request type for the Query/Params RPC method. @@ -28,3 +34,15 @@ message QueryParamsResponse { (amino.dont_omitempty) = true ]; } + +// QueryVoteExtBodyByHeightRequest defines the QueryVoteExtBodyByHeightRequest message. +message QueryVoteExtBodyByHeightRequest { + int64 block_height = 1; +} + +// QueryVoteExtBodyByHeightResponse defines the QueryVoteExtBodyByHeightResponse message. +message QueryVoteExtBodyByHeightResponse { + bytes next_validator_set_hash = 1; + bytes current_state_root = 2; + int64 current_block_height = 3; +} diff --git a/x/pulsar/types/genesis.pb.go b/x/pulsar/types/genesis.pb.go index 65be9de9..acfbe019 100644 --- a/x/pulsar/types/genesis.pb.go +++ b/x/pulsar/types/genesis.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/module.pb.go b/x/pulsar/types/module.pb.go index eeab9504..b7ffd5c3 100644 --- a/x/pulsar/types/module.pb.go +++ b/x/pulsar/types/module.pb.go @@ -4,13 +4,12 @@ package types import ( + _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" - - _ "cosmossdk.io/api/cosmos/app/v1alpha1" - proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/params.pb.go b/x/pulsar/types/params.pb.go index e7a05515..0480a17b 100644 --- a/x/pulsar/types/params.pb.go +++ b/x/pulsar/types/params.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/query.pb.go b/x/pulsar/types/query.pb.go index 8df04fb5..0c09f00a 100644 --- a/x/pulsar/types/query.pb.go +++ b/x/pulsar/types/query.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/tx.pb.go b/x/pulsar/types/tx.pb.go index 2f343e52..e3271589 100644 --- a/x/pulsar/types/tx.pb.go +++ b/x/pulsar/types/tx.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/keeper/query_vote_ext_body_by_height.go b/x/votepersistence/keeper/query_vote_ext_body_by_height.go new file mode 100644 index 00000000..51cb899a --- /dev/null +++ b/x/votepersistence/keeper/query_vote_ext_body_by_height.go @@ -0,0 +1,17 @@ +package keeper + +import ( + "context" + + "github.com/node101-io/pulsar-chain/x/votepersistence/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (q queryServer) VoteExtBodyByHeight(ctx context.Context, req *types.QueryVoteExtBodyByHeightRequest) (*types.QueryVoteExtBodyByHeightResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + return &types.QueryVoteExtBodyByHeightResponse{}, nil +} diff --git a/x/votepersistence/module/autocli.go b/x/votepersistence/module/autocli.go index 6fc3fdaf..41ede925 100644 --- a/x/votepersistence/module/autocli.go +++ b/x/votepersistence/module/autocli.go @@ -17,6 +17,13 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Use: "params", Short: "Shows the parameters of the module", }, + { + RpcMethod: "VoteExtBodyByHeight", + Use: "vote-ext-body-by-height [block-height]", + Short: "Query vote-ext-body-by-height", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "block_height"}}, + }, + // this line is used by ignite scaffolding # autocli/query }, }, diff --git a/x/votepersistence/types/genesis.pb.go b/x/votepersistence/types/genesis.pb.go index 9c48d742..e252c7ba 100644 --- a/x/votepersistence/types/genesis.pb.go +++ b/x/votepersistence/types/genesis.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/module.pb.go b/x/votepersistence/types/module.pb.go index 15faa0b1..319820ca 100644 --- a/x/votepersistence/types/module.pb.go +++ b/x/votepersistence/types/module.pb.go @@ -4,13 +4,12 @@ package types import ( + _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" - - _ "cosmossdk.io/api/cosmos/app/v1alpha1" - proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/params.pb.go b/x/votepersistence/types/params.pb.go index db7a5855..3d572a3f 100644 --- a/x/votepersistence/types/params.pb.go +++ b/x/votepersistence/types/params.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/query.pb.go b/x/votepersistence/types/query.pb.go index 7f0e6273..07721a5a 100644 --- a/x/votepersistence/types/query.pb.go +++ b/x/votepersistence/types/query.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. @@ -115,9 +114,117 @@ func (m *QueryParamsResponse) GetParams() Params { return Params{} } +// QueryVoteExtBodyByHeightRequest defines the QueryVoteExtBodyByHeightRequest message. +type QueryVoteExtBodyByHeightRequest struct { + BlockHeight int64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` +} + +func (m *QueryVoteExtBodyByHeightRequest) Reset() { *m = QueryVoteExtBodyByHeightRequest{} } +func (m *QueryVoteExtBodyByHeightRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVoteExtBodyByHeightRequest) ProtoMessage() {} +func (*QueryVoteExtBodyByHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2c9976ecef977273, []int{2} +} +func (m *QueryVoteExtBodyByHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteExtBodyByHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteExtBodyByHeightRequest.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 *QueryVoteExtBodyByHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteExtBodyByHeightRequest.Merge(m, src) +} +func (m *QueryVoteExtBodyByHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteExtBodyByHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteExtBodyByHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteExtBodyByHeightRequest proto.InternalMessageInfo + +func (m *QueryVoteExtBodyByHeightRequest) GetBlockHeight() int64 { + if m != nil { + return m.BlockHeight + } + return 0 +} + +// QueryVoteExtBodyByHeightResponse defines the QueryVoteExtBodyByHeightResponse message. +type QueryVoteExtBodyByHeightResponse struct { + NextValidatorSetHash []byte `protobuf:"bytes,1,opt,name=next_validator_set_hash,json=nextValidatorSetHash,proto3" json:"next_validator_set_hash,omitempty"` + CurrentStateRoot []byte `protobuf:"bytes,2,opt,name=current_state_root,json=currentStateRoot,proto3" json:"current_state_root,omitempty"` + CurrentBlockHeight int64 `protobuf:"varint,3,opt,name=current_block_height,json=currentBlockHeight,proto3" json:"current_block_height,omitempty"` +} + +func (m *QueryVoteExtBodyByHeightResponse) Reset() { *m = QueryVoteExtBodyByHeightResponse{} } +func (m *QueryVoteExtBodyByHeightResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVoteExtBodyByHeightResponse) ProtoMessage() {} +func (*QueryVoteExtBodyByHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2c9976ecef977273, []int{3} +} +func (m *QueryVoteExtBodyByHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteExtBodyByHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteExtBodyByHeightResponse.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 *QueryVoteExtBodyByHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteExtBodyByHeightResponse.Merge(m, src) +} +func (m *QueryVoteExtBodyByHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteExtBodyByHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteExtBodyByHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteExtBodyByHeightResponse proto.InternalMessageInfo + +func (m *QueryVoteExtBodyByHeightResponse) GetNextValidatorSetHash() []byte { + if m != nil { + return m.NextValidatorSetHash + } + return nil +} + +func (m *QueryVoteExtBodyByHeightResponse) GetCurrentStateRoot() []byte { + if m != nil { + return m.CurrentStateRoot + } + return nil +} + +func (m *QueryVoteExtBodyByHeightResponse) GetCurrentBlockHeight() int64 { + if m != nil { + return m.CurrentBlockHeight + } + return 0 +} + func init() { proto.RegisterType((*QueryParamsRequest)(nil), "pulsarchain.votepersistence.v1.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "pulsarchain.votepersistence.v1.QueryParamsResponse") + proto.RegisterType((*QueryVoteExtBodyByHeightRequest)(nil), "pulsarchain.votepersistence.v1.QueryVoteExtBodyByHeightRequest") + proto.RegisterType((*QueryVoteExtBodyByHeightResponse)(nil), "pulsarchain.votepersistence.v1.QueryVoteExtBodyByHeightResponse") } func init() { @@ -125,29 +232,41 @@ func init() { } var fileDescriptor_2c9976ecef977273 = []byte{ - // 342 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xb1, 0x4a, 0x3b, 0x41, - 0x10, 0xc6, 0x6f, 0xff, 0xf0, 0x0f, 0x78, 0x56, 0x9e, 0x29, 0x24, 0xc8, 0x2a, 0x29, 0x44, 0x22, - 0xb9, 0xf5, 0x2e, 0x56, 0x29, 0xd3, 0xd9, 0x69, 0xb0, 0xb2, 0x72, 0xef, 0x1c, 0x2e, 0x0b, 0xb9, - 0x9d, 0xcd, 0xed, 0xde, 0x61, 0x5a, 0x9f, 0x40, 0xf0, 0x25, 0x6c, 0x04, 0x3b, 0x5f, 0x21, 0x65, - 0xc0, 0xc6, 0x4a, 0x24, 0x11, 0x7c, 0x0d, 0xc9, 0xed, 0x15, 0x6a, 0xd0, 0x60, 0xb3, 0x0c, 0xdf, - 0x7e, 0xdf, 0x6f, 0x66, 0x76, 0xdd, 0x96, 0xca, 0x87, 0x9a, 0x67, 0xf1, 0x80, 0x0b, 0xc9, 0x0a, - 0x34, 0xa0, 0x20, 0xd3, 0x42, 0x1b, 0x90, 0x31, 0xb0, 0x22, 0x60, 0xa3, 0x1c, 0xb2, 0xb1, 0xaf, - 0x32, 0x34, 0xe8, 0xd1, 0x4f, 0x5e, 0xff, 0x9b, 0xd7, 0x2f, 0x82, 0xc6, 0x06, 0x4f, 0x85, 0x44, - 0x56, 0x9e, 0x36, 0xd2, 0xa8, 0x27, 0x98, 0x60, 0x59, 0xb2, 0x45, 0x55, 0xa9, 0xdb, 0x09, 0x62, - 0x32, 0x04, 0xc6, 0x95, 0x60, 0x5c, 0x4a, 0x34, 0xdc, 0x08, 0x94, 0xba, 0xba, 0x6d, 0xc5, 0xa8, - 0x53, 0xd4, 0x2c, 0xe2, 0x1a, 0x6c, 0x7f, 0x56, 0x04, 0x11, 0x18, 0x1e, 0x30, 0xc5, 0x13, 0x21, - 0x4b, 0x73, 0xe5, 0x3d, 0x58, 0x31, 0xbe, 0xe2, 0x19, 0x4f, 0x2b, 0x70, 0xb3, 0xee, 0x7a, 0xa7, - 0x0b, 0xdc, 0x49, 0x29, 0xf6, 0x61, 0x94, 0x83, 0x36, 0xcd, 0x0b, 0x77, 0xf3, 0x8b, 0xaa, 0x15, - 0x4a, 0x0d, 0xde, 0xb1, 0x5b, 0xb3, 0xe1, 0x2d, 0xb2, 0x4b, 0xf6, 0xd7, 0xc3, 0x3d, 0xff, 0xf7, - 0xed, 0x7d, 0x9b, 0xef, 0xad, 0x4d, 0x5e, 0x76, 0x9c, 0xbb, 0xf7, 0x87, 0x16, 0xe9, 0x57, 0x80, - 0xf0, 0x91, 0xb8, 0xff, 0xcb, 0x16, 0xde, 0x3d, 0x71, 0x6b, 0xd6, 0xe7, 0x85, 0xab, 0x78, 0xcb, - 0xa3, 0x36, 0x3a, 0x7f, 0xca, 0xd8, 0x45, 0x9a, 0xdd, 0xeb, 0xa7, 0xb7, 0xdb, 0x7f, 0x47, 0x5e, - 0xc8, 0x24, 0x5e, 0x42, 0x70, 0x18, 0xb4, 0x05, 0x32, 0xcb, 0x69, 0xaf, 0x78, 0xb7, 0xde, 0xd9, - 0x64, 0x46, 0xc9, 0x74, 0x46, 0xc9, 0xeb, 0x8c, 0x92, 0x9b, 0x39, 0x75, 0xa6, 0x73, 0xea, 0x3c, - 0xcf, 0xa9, 0x73, 0xde, 0x4d, 0x84, 0x19, 0xe4, 0x91, 0x1f, 0x63, 0xfa, 0x23, 0xf7, 0x6a, 0x89, - 0x6c, 0xc6, 0x0a, 0x74, 0x54, 0x2b, 0xbf, 0xa3, 0xf3, 0x11, 0x00, 0x00, 0xff, 0xff, 0x9b, 0x87, - 0xdc, 0x4b, 0x7c, 0x02, 0x00, 0x00, + // 529 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x8d, 0x1b, 0x11, 0x89, 0x6d, 0x0f, 0xb0, 0x8d, 0x44, 0x15, 0x21, 0xb7, 0xe4, 0x80, 0x50, + 0xa0, 0xde, 0x3a, 0x85, 0x4b, 0x2f, 0xa0, 0x08, 0xa4, 0x72, 0x03, 0xb7, 0xea, 0xa1, 0x17, 0xb3, + 0x76, 0x56, 0xb6, 0x45, 0xb2, 0xe3, 0x7a, 0x27, 0x56, 0x2c, 0xc4, 0x85, 0x2f, 0x40, 0xe2, 0x27, + 0xb8, 0x80, 0xb8, 0xf2, 0x07, 0x3d, 0x56, 0xe2, 0xc2, 0x09, 0xa1, 0x04, 0x89, 0x1f, 0xe0, 0x03, + 0x90, 0xd7, 0x1b, 0xd1, 0x52, 0x42, 0x28, 0x97, 0xc8, 0x7a, 0xf3, 0xde, 0x9b, 0x37, 0x33, 0x1b, + 0xd2, 0x49, 0x47, 0x03, 0xc5, 0xb3, 0x30, 0xe6, 0x89, 0x64, 0x39, 0xa0, 0x48, 0x45, 0xa6, 0x12, + 0x85, 0x42, 0x86, 0x82, 0xe5, 0x2e, 0x3b, 0x1a, 0x89, 0xac, 0x70, 0xd2, 0x0c, 0x10, 0xa8, 0x7d, + 0x8a, 0xeb, 0xfc, 0xc6, 0x75, 0x72, 0xb7, 0x75, 0x95, 0x0f, 0x13, 0x09, 0x4c, 0xff, 0x56, 0x92, + 0x56, 0x27, 0x04, 0x35, 0x04, 0xc5, 0x02, 0xae, 0x44, 0xe5, 0xc5, 0x72, 0x37, 0x10, 0xc8, 0x5d, + 0x96, 0xf2, 0x28, 0x91, 0x1c, 0x13, 0x90, 0x86, 0xdb, 0x8c, 0x20, 0x02, 0xfd, 0xc9, 0xca, 0x2f, + 0x83, 0x5e, 0x8f, 0x00, 0xa2, 0x81, 0x60, 0x3c, 0x4d, 0x18, 0x97, 0x12, 0x50, 0x4b, 0x94, 0xa9, + 0xde, 0x5e, 0x10, 0x3f, 0xe5, 0x19, 0x1f, 0x1a, 0x72, 0xbb, 0x49, 0xe8, 0xd3, 0x32, 0xc2, 0x13, + 0x0d, 0x7a, 0xe2, 0x68, 0x24, 0x14, 0xb6, 0x9f, 0x91, 0xd5, 0x33, 0xa8, 0x4a, 0x41, 0x2a, 0x41, + 0x1f, 0x93, 0x46, 0x25, 0x5e, 0xb3, 0x36, 0xac, 0x5b, 0xcb, 0xdd, 0x9b, 0xce, 0xdf, 0xa7, 0x77, + 0x2a, 0x7d, 0xef, 0xf2, 0xf1, 0x97, 0xf5, 0xda, 0xdb, 0xef, 0x1f, 0x3a, 0x96, 0x67, 0x0c, 0xda, + 0x0f, 0xc9, 0xba, 0xee, 0x70, 0x00, 0x28, 0x1e, 0x8d, 0xb1, 0x07, 0xfd, 0xa2, 0x57, 0xec, 0x8a, + 0x24, 0x8a, 0xd1, 0x84, 0xa0, 0x37, 0xc8, 0x4a, 0x30, 0x80, 0xf0, 0xb9, 0x1f, 0x6b, 0x58, 0xf7, + 0xac, 0x7b, 0xcb, 0x1a, 0xab, 0x98, 0xed, 0x8f, 0x16, 0xd9, 0x98, 0x6f, 0x63, 0x52, 0xdf, 0x23, + 0xd7, 0xa4, 0x18, 0xa3, 0x9f, 0xf3, 0x41, 0xd2, 0xe7, 0x08, 0x99, 0xaf, 0x04, 0xfa, 0x31, 0x57, + 0xb1, 0xb6, 0x5c, 0xf1, 0x9a, 0x65, 0xf9, 0x60, 0x56, 0xdd, 0x13, 0xb8, 0xcb, 0x55, 0x4c, 0xef, + 0x10, 0x1a, 0x8e, 0xb2, 0x4c, 0x48, 0xf4, 0x15, 0x72, 0x14, 0x7e, 0x06, 0x80, 0x6b, 0x4b, 0x5a, + 0x71, 0xc5, 0x54, 0xf6, 0xca, 0x82, 0x07, 0x80, 0x74, 0x8b, 0x34, 0x67, 0xec, 0x33, 0xa1, 0xeb, + 0x3a, 0xf4, 0xcc, 0xa9, 0xf7, 0x2b, 0x7b, 0xf7, 0x7d, 0x9d, 0x5c, 0xd2, 0xd9, 0xe9, 0x3b, 0x8b, + 0x34, 0xaa, 0x4d, 0xd1, 0xee, 0xa2, 0x8d, 0x9e, 0x3f, 0x56, 0x6b, 0xfb, 0x42, 0x9a, 0x6a, 0x29, + 0xed, 0x9d, 0x57, 0x9f, 0xbe, 0xbd, 0x59, 0xba, 0x4b, 0xbb, 0x4c, 0x42, 0x5f, 0xb8, 0x5b, 0xee, + 0x66, 0x02, 0xac, 0xf2, 0xd9, 0x5c, 0xf0, 0x72, 0xe8, 0x0f, 0x8b, 0xac, 0xfe, 0x61, 0xe1, 0xf4, + 0xfe, 0x3f, 0x05, 0x99, 0x7f, 0xf1, 0xd6, 0x83, 0xff, 0x37, 0x30, 0x63, 0x1d, 0xea, 0xb1, 0xf6, + 0xa9, 0x77, 0x91, 0xb1, 0x4a, 0xc8, 0x2f, 0x5f, 0x48, 0x00, 0xfd, 0xc2, 0x0f, 0x0a, 0x73, 0x3b, + 0xf6, 0xe2, 0xf4, 0x25, 0x5f, 0xf6, 0xf6, 0x8f, 0x27, 0xb6, 0x75, 0x32, 0xb1, 0xad, 0xaf, 0x13, + 0xdb, 0x7a, 0x3d, 0xb5, 0x6b, 0x27, 0x53, 0xbb, 0xf6, 0x79, 0x6a, 0xd7, 0x0e, 0x77, 0xa2, 0x04, + 0xe3, 0x51, 0xe0, 0x84, 0x30, 0x9c, 0xdb, 0x77, 0x7c, 0xae, 0x33, 0x16, 0xa9, 0x50, 0x41, 0x43, + 0xff, 0x0f, 0xb7, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0x7d, 0x4c, 0x67, 0xcd, 0x75, 0x04, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -164,6 +283,8 @@ const _ = grpc.SupportPackageIsVersion4 type QueryClient interface { // Parameters queries the parameters of the module. Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) + // VoteExtBodyByHeight Queries a list of VoteExtBodyByHeight items. + VoteExtBodyByHeight(ctx context.Context, in *QueryVoteExtBodyByHeightRequest, opts ...grpc.CallOption) (*QueryVoteExtBodyByHeightResponse, error) } type queryClient struct { @@ -183,10 +304,21 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . return out, nil } +func (c *queryClient) VoteExtBodyByHeight(ctx context.Context, in *QueryVoteExtBodyByHeightRequest, opts ...grpc.CallOption) (*QueryVoteExtBodyByHeightResponse, error) { + out := new(QueryVoteExtBodyByHeightResponse) + err := c.cc.Invoke(ctx, "/pulsarchain.votepersistence.v1.Query/VoteExtBodyByHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Parameters queries the parameters of the module. Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) + // VoteExtBodyByHeight Queries a list of VoteExtBodyByHeight items. + VoteExtBodyByHeight(context.Context, *QueryVoteExtBodyByHeightRequest) (*QueryVoteExtBodyByHeightResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -196,6 +328,9 @@ type UnimplementedQueryServer struct { func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") } +func (*UnimplementedQueryServer) VoteExtBodyByHeight(ctx context.Context, req *QueryVoteExtBodyByHeightRequest) (*QueryVoteExtBodyByHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VoteExtBodyByHeight not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -219,6 +354,24 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf return interceptor(ctx, in, info, handler) } +func _Query_VoteExtBodyByHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVoteExtBodyByHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).VoteExtBodyByHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pulsarchain.votepersistence.v1.Query/VoteExtBodyByHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).VoteExtBodyByHeight(ctx, req.(*QueryVoteExtBodyByHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + var Query_serviceDesc = _Query_serviceDesc var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "pulsarchain.votepersistence.v1.Query", @@ -228,6 +381,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "Params", Handler: _Query_Params_Handler, }, + { + MethodName: "VoteExtBodyByHeight", + Handler: _Query_VoteExtBodyByHeight_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "pulsarchain/votepersistence/v1/query.proto", @@ -289,6 +446,76 @@ func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *QueryVoteExtBodyByHeightRequest) 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 *QueryVoteExtBodyByHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteExtBodyByHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BlockHeight != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.BlockHeight)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryVoteExtBodyByHeightResponse) 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 *QueryVoteExtBodyByHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteExtBodyByHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CurrentBlockHeight != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CurrentBlockHeight)) + i-- + dAtA[i] = 0x18 + } + if len(m.CurrentStateRoot) > 0 { + i -= len(m.CurrentStateRoot) + copy(dAtA[i:], m.CurrentStateRoot) + i = encodeVarintQuery(dAtA, i, uint64(len(m.CurrentStateRoot))) + i-- + dAtA[i] = 0x12 + } + if len(m.NextValidatorSetHash) > 0 { + i -= len(m.NextValidatorSetHash) + copy(dAtA[i:], m.NextValidatorSetHash) + i = encodeVarintQuery(dAtA, i, uint64(len(m.NextValidatorSetHash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -320,6 +547,38 @@ func (m *QueryParamsResponse) Size() (n int) { return n } +func (m *QueryVoteExtBodyByHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BlockHeight != 0 { + n += 1 + sovQuery(uint64(m.BlockHeight)) + } + return n +} + +func (m *QueryVoteExtBodyByHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NextValidatorSetHash) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.CurrentStateRoot) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.CurrentBlockHeight != 0 { + n += 1 + sovQuery(uint64(m.CurrentBlockHeight)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -459,6 +718,212 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryVoteExtBodyByHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryVoteExtBodyByHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteExtBodyByHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockHeight", wireType) + } + m.BlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVoteExtBodyByHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryVoteExtBodyByHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteExtBodyByHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorSetHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorSetHash = append(m.NextValidatorSetHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorSetHash == nil { + m.NextValidatorSetHash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentStateRoot", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CurrentStateRoot = append(m.CurrentStateRoot[:0], dAtA[iNdEx:postIndex]...) + if m.CurrentStateRoot == nil { + m.CurrentStateRoot = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentBlockHeight", wireType) + } + m.CurrentBlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CurrentBlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/votepersistence/types/query.pb.gw.go b/x/votepersistence/types/query.pb.gw.go index 699c42c3..dbc762c5 100644 --- a/x/votepersistence/types/query.pb.gw.go +++ b/x/votepersistence/types/query.pb.gw.go @@ -51,6 +51,60 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal } +func request_Query_VoteExtBodyByHeight_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteExtBodyByHeightRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["block_height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "block_height") + } + + protoReq.BlockHeight, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "block_height", err) + } + + msg, err := client.VoteExtBodyByHeight(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_VoteExtBodyByHeight_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteExtBodyByHeightRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["block_height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "block_height") + } + + protoReq.BlockHeight, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "block_height", err) + } + + msg, err := server.VoteExtBodyByHeight(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -80,6 +134,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_VoteExtBodyByHeight_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_VoteExtBodyByHeight_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VoteExtBodyByHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -141,13 +218,37 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_VoteExtBodyByHeight_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_VoteExtBodyByHeight_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VoteExtBodyByHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } var ( pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"node101-io", "pulsar-chain", "votepersistence", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_VoteExtBodyByHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"node101-io", "pulsar-chain", "votepersistence", "v1", "vote_ext_body_by_height", "block_height"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_VoteExtBodyByHeight_0 = runtime.ForwardResponseMessage ) diff --git a/x/votepersistence/types/tx.pb.go b/x/votepersistence/types/tx.pb.go index c72264a0..31772b17 100644 --- a/x/votepersistence/types/tx.pb.go +++ b/x/votepersistence/types/tx.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. From f5669bcf38518542a129e0ff8ba1a0489b6c0a1a Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2026 21:46:50 +0300 Subject: [PATCH 18/63] fix: define errors in vote persistence module to use in abci handler --- abci/helpers.go | 5 +++-- x/votepersistence/types/errors.go | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/abci/helpers.go b/abci/helpers.go index 47a190c0..57d61233 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -17,6 +17,7 @@ import ( "github.com/node101-io/mina-signer-go/poseidon" keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" votepersistence "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" + "github.com/node101-io/pulsar-chain/x/votepersistence/types" ) type SecondaryKey struct { @@ -47,7 +48,7 @@ func (h *AbciHandler) verifyVoteExtension(ctx context.Context, txs [][]byte, bod voteExtensionTx := txs[0] if !strings.Contains(string(txs[0]), VoteExtMarker) { - return fmt.Errorf("") + return types.ErrVoteExtMarkerNotFound } voteExtensionTx = voteExtensionTx[len([]byte(VoteExtMarker)):] @@ -80,7 +81,7 @@ func (h *AbciHandler) verifyVoteExtension(ctx context.Context, txs [][]byte, bod } if !MockSignatureVerify(vote, body, minaKey, ActionsReducedRoot) { - return fmt.Errorf("") + return types.ErrInvalidVoteExtension.Wrap("invalid signature") } } diff --git a/x/votepersistence/types/errors.go b/x/votepersistence/types/errors.go index c489914c..f8af82ba 100644 --- a/x/votepersistence/types/errors.go +++ b/x/votepersistence/types/errors.go @@ -8,5 +8,7 @@ import ( // x/votepersistence module sentinel errors var ( - ErrInvalidSigner = errors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") + ErrInvalidSigner = errors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") + ErrVoteExtMarkerNotFound = errors.Register(ModuleName, 1101, "vote extension marker not found") + ErrInvalidVoteExtension = errors.Register(ModuleName, 1102, "invalid vote extension") ) From aa2b33b23bcfdfef3713b503abab36e4b80b1bce Mon Sep 17 00:00:00 2001 From: Yusuf Date: Thu, 30 Apr 2026 21:12:09 +0300 Subject: [PATCH 19/63] fix: use get validator by cons add instead of get validator, and fix the mina key unmarshalling problem --- abci/helpers.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/abci/helpers.go b/abci/helpers.go index 57d61233..c1899838 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -126,7 +126,7 @@ func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []valid for _, validator := range valInfo { input = []*big.Int{} - cosmosValidatorInfo, err := h.stakingKeeper.Validator(ctx, validator.ConsensusAddr) + cosmosValidatorInfo, err := h.stakingKeeper.GetValidatorByConsAddr(ctx, validator.ConsensusAddr) if err != nil { return nil, err } @@ -149,7 +149,8 @@ func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []valid return nil, err } - MinaPublicKey, err := keys.PublicKey{}.FromAddress(string(minaPubKey)) + var MinaPublicKey keys.PublicKey + err = MinaPublicKey.Unmarshal(minaPubKey) if err != nil { return nil, err } @@ -251,7 +252,8 @@ func (h *AbciHandler) constructVoteExtBody(ctx sdk.Context, blockHeight int64) ( } func (h *AbciHandler) getValidatorPublicKey(ctx sdk.Context, validatorAddr []byte) ([]byte, error) { - cosmosValidatorInfo, err := h.stakingKeeper.Validator(ctx, validatorAddr) + + cosmosValidatorInfo, err := h.stakingKeeper.GetValidatorByConsAddr(ctx, validatorAddr) if err != nil { return nil, err } From ba8ef0a0c523bb07fa59d0ffd7820253b8e86b0d Mon Sep 17 00:00:00 2001 From: Yusuf Date: Thu, 30 Apr 2026 21:33:07 +0300 Subject: [PATCH 20/63] fix: seperate vote ext body construct functions --- abci/helpers.go | 70 +++++++++++++++++++++++++++++++++++++--- abci/pre_blocker.go | 2 +- abci/process_proposal.go | 2 +- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/abci/helpers.go b/abci/helpers.go index c1899838..cab16eb4 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -11,6 +11,7 @@ import ( abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/node101-io/mina-signer-go/constants" "github.com/node101-io/mina-signer-go/field" "github.com/node101-io/mina-signer-go/keys" @@ -89,7 +90,8 @@ func (h *AbciHandler) verifyVoteExtension(ctx context.Context, txs [][]byte, bod return nil } -func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]validatorInfo, error) { +// Use if you need the validator set of block < N where N is the current block number. +func (h *AbciHandler) getHistoricalValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]validatorInfo, error) { historicalData, err := h.stakingKeeper.GetHistoricalInfo(ctx, currentBlockHeight) if err != nil { @@ -117,6 +119,37 @@ func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) return valInfo, nil } +// Use if you need the validator set of the current block +func (h *AbciHandler) getCurrentValidatorSet(ctx sdk.Context) ([]validatorInfo, error) { + + var valInfo []validatorInfo + var iterErr error + + err := h.stakingKeeper.IterateLastValidators(ctx, func(index int64, validator stakingTypes.ValidatorI) (stop bool) { + consAddr, err := validator.GetConsAddr() + if err != nil { + iterErr = err + return true + } + + valInfo = append(valInfo, validatorInfo{ + ConsensusAddr: consAddr, + Power: validator.GetConsensusPower(sdk.DefaultPowerReduction), + }) + + return false + }) + + if err != nil { + return nil, err + } + if iterErr != nil { + return nil, iterErr + } + + return valInfo, nil +} + // TODO: Move this helper to mina-signer-go func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []validatorInfo, poseidonHash *poseidon.Poseidon) (*big.Int, error) { @@ -181,7 +214,7 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, txs [] valInfoMap := make(map[string]validatorInfo) - currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) + currentValidatorSet, err := h.getHistoricalValidatorSet(ctx, blockHeight-2) if err != nil { return false, err } @@ -224,7 +257,36 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, txs [] func (h *AbciHandler) constructVoteExtBody(ctx sdk.Context, blockHeight int64) (VoteExtensionBody, error) { - nextValidatorSet, err := h.getValidatorSet(ctx, blockHeight) + nextValidatorSet, err := h.getCurrentValidatorSet(ctx) + if err != nil { + return VoteExtensionBody{}, err + } + + currentBlockInfo, err := h.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-1) + if err != nil { + return VoteExtensionBody{}, err + } + + poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) + + nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, nextValidatorSet, poseidonHash) + if err != nil { + return VoteExtensionBody{}, err + } + if nextValidatorSetHash == nil { + return VoteExtensionBody{}, err + } + + return VoteExtensionBody{ + NextValidatorSetHash: nextValidatorSetHash.Bytes(), + CurrentStateRoot: currentBlockInfo.Header.AppHash, + CurrentBlockHeight: blockHeight - 1, + }, nil +} + +func (h *AbciHandler) reconstructVoteExtBody(ctx sdk.Context, blockHeight int64) (VoteExtensionBody, error) { + + nextValidatorSet, err := h.getHistoricalValidatorSet(ctx, blockHeight) if err != nil { return VoteExtensionBody{}, err } @@ -269,7 +331,7 @@ func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteE voteExtsForGivenBlock := make(map[string][]byte) currentValidatorSetMap := make(map[string]bool) - currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) + currentValidatorSet, err := h.getHistoricalValidatorSet(ctx, blockHeight-2) if err != nil { return payload{}, err } diff --git a/abci/pre_blocker.go b/abci/pre_blocker.go index 31f31a88..a00365c5 100644 --- a/abci/pre_blocker.go +++ b/abci/pre_blocker.go @@ -33,7 +33,7 @@ func (h *AbciHandler) PreBlocker() sdk.PreBlocker { return nil, err } - currentValidatorSet, err := h.getValidatorSet(ctx, req.GetHeight()-2) + currentValidatorSet, err := h.getHistoricalValidatorSet(ctx, req.GetHeight()-2) if err != nil { return nil, err } diff --git a/abci/process_proposal.go b/abci/process_proposal.go index c3184ea6..6d239e07 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -16,7 +16,7 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil } - body, err := h.constructVoteExtBody(ctx, req.GetHeight()-1) + body, err := h.reconstructVoteExtBody(ctx, req.GetHeight()-1) if err != nil { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } From 1ee21bed731f95f43ff17530fe1649a3530f4afc Mon Sep 17 00:00:00 2001 From: Yusuf Date: Thu, 30 Apr 2026 22:29:14 +0300 Subject: [PATCH 21/63] feat: implement vote extension body query --- x/votepersistence/keeper/keeper.go | 20 ++-- x/votepersistence/keeper/keeper_test.go | 2 + .../keeper/query_vote_ext_body_by_height.go | 105 +++++++++++++++++- x/votepersistence/module/depinject.go | 10 +- x/votepersistence/types/expected_keepers.go | 10 ++ 5 files changed, 137 insertions(+), 10 deletions(-) diff --git a/x/votepersistence/keeper/keeper.go b/x/votepersistence/keeper/keeper.go index 1b43d965..83ac0d67 100644 --- a/x/votepersistence/keeper/keeper.go +++ b/x/votepersistence/keeper/keeper.go @@ -15,9 +15,11 @@ import ( const VoteStorageMapName string = "vote_storage" type Keeper struct { - storeService corestore.KVStoreService - cdc codec.Codec - addressCodec address.Codec + storeService corestore.KVStoreService + cdc codec.Codec + addressCodec address.Codec + stakingKeeper types.StakingKeeper + keyregistryKeeper types.KeyregistryKeeper // Address capable of executing a MsgUpdateParams message. // Typically, this should be the x/gov module account. authority []byte @@ -32,6 +34,8 @@ func NewKeeper( storeService corestore.KVStoreService, cdc codec.Codec, addressCodec address.Codec, + stakingKeeper types.StakingKeeper, + keyregistryKeeper types.KeyregistryKeeper, authority []byte, ) Keeper { @@ -42,10 +46,12 @@ func NewKeeper( sb := collections.NewSchemaBuilder(storeService) k := Keeper{ - storeService: storeService, - cdc: cdc, - addressCodec: addressCodec, - authority: authority, + storeService: storeService, + cdc: cdc, + addressCodec: addressCodec, + stakingKeeper: stakingKeeper, + keyregistryKeeper: keyregistryKeeper, + authority: authority, Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), diff --git a/x/votepersistence/keeper/keeper_test.go b/x/votepersistence/keeper/keeper_test.go index 250ed52c..d892a036 100644 --- a/x/votepersistence/keeper/keeper_test.go +++ b/x/votepersistence/keeper/keeper_test.go @@ -40,6 +40,8 @@ func initFixture(t *testing.T) *fixture { storeService, encCfg.Codec, addressCodec, + nil, + nil, authority, ) diff --git a/x/votepersistence/keeper/query_vote_ext_body_by_height.go b/x/votepersistence/keeper/query_vote_ext_body_by_height.go index 51cb899a..5bfcf446 100644 --- a/x/votepersistence/keeper/query_vote_ext_body_by_height.go +++ b/x/votepersistence/keeper/query_vote_ext_body_by_height.go @@ -2,7 +2,16 @@ package keeper import ( "context" + "errors" + "fmt" + "math/big" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/node101-io/mina-signer-go/constants" + "github.com/node101-io/mina-signer-go/field" + "github.com/node101-io/mina-signer-go/keys" + "github.com/node101-io/mina-signer-go/poseidon" "github.com/node101-io/pulsar-chain/x/votepersistence/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -13,5 +22,99 @@ func (q queryServer) VoteExtBodyByHeight(ctx context.Context, req *types.QueryVo return nil, status.Error(codes.InvalidArgument, "invalid request") } - return &types.QueryVoteExtBodyByHeightResponse{}, nil + if req.BlockHeight < 4 { + return nil, status.Error(codes.InvalidArgument, "there is no vote extension in blocks smaller than 4") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + if req.BlockHeight == sdkCtx.BlockHeight() { + return nil, status.Error(codes.InvalidArgument, "no vote extensions in this block yet") + } + + if q.k.stakingKeeper == nil || q.k.keyregistryKeeper == nil { + return nil, status.Error(codes.Internal, "vote extension query dependencies are not configured") + } + + return q.constructVoteExtBodyByHeight(ctx, req.BlockHeight) +} + +func (q queryServer) constructVoteExtBodyByHeight(ctx context.Context, blockHeight int64) (*types.QueryVoteExtBodyByHeightResponse, error) { + currentBlockInfo, err := q.k.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-2) + if err != nil { + return nil, wrapHistoricalInfoError(blockHeight, err) + } + + nextBlockInfo, err := q.k.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-1) + if err != nil { + return nil, wrapHistoricalInfoError(blockHeight+1, err) + } + + nextValidatorSetHash, err := q.calculateValidatorSetRoot(ctx, nextBlockInfo.Valset) + if err != nil { + return nil, err + } + + return &types.QueryVoteExtBodyByHeightResponse{ + NextValidatorSetHash: nextValidatorSetHash, + CurrentStateRoot: currentBlockInfo.Header.AppHash, + CurrentBlockHeight: blockHeight - 1, + }, nil +} + +func (q queryServer) calculateValidatorSetRoot(ctx context.Context, validatorSet []stakingtypes.Validator) ([]byte, error) { + + poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) + merkleRoot := poseidonHash.Hash([]*big.Int{big.NewInt(0)}) + + for _, validator := range validatorSet { + cosmosValidatorPubKey, err := validator.ConsPubKey() + if err != nil { + return nil, status.Error(codes.Internal, "failed to read validator consensus public key") + } + + exists, err := q.k.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, cosmosValidatorPubKey.Bytes()) + if err != nil { + return nil, status.Error(codes.Internal, "failed to check validator Mina key") + } + if !exists { + return nil, status.Errorf(codes.NotFound, "validator Mina key not found for consensus public key %X", cosmosValidatorPubKey.Bytes()) + } + + minaPubKey, err := q.k.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, cosmosValidatorPubKey.Bytes()) + if err != nil { + return nil, status.Error(codes.Internal, "failed to load validator Mina key") + } + + var minaPublicKey keys.PublicKey + err = minaPublicKey.Unmarshal(minaPubKey) + if err != nil { + return nil, status.Error(codes.Internal, "failed to decode validator Mina public key") + } + + input := []*big.Int{minaPublicKey.X} + if minaPublicKey.IsOdd { + input = append(input, big.NewInt(1)) + } else { + input = append(input, big.NewInt(0)) + } + input = append(input, big.NewInt(validator.ConsensusPower(sdk.DefaultPowerReduction))) + + hashOfValidator := poseidonHash.Hash(input) + merkleRoot = poseidonHash.Hash([]*big.Int{merkleRoot, hashOfValidator}) + } + + if merkleRoot == nil { + return nil, status.Error(codes.Internal, "failed to calculate next validator set hash") + } + + return merkleRoot.Bytes(), nil +} + +func wrapHistoricalInfoError(height int64, err error) error { + if errors.Is(err, stakingtypes.ErrNoHistoricalInfo) { + return status.Errorf(codes.NotFound, "historical info not found for height %d", height) + } + + return status.Error(codes.Internal, fmt.Sprintf("failed to load staking historical info for height %d", height)) } diff --git a/x/votepersistence/module/depinject.go b/x/votepersistence/module/depinject.go index 5a393590..4d6c1c43 100644 --- a/x/votepersistence/module/depinject.go +++ b/x/votepersistence/module/depinject.go @@ -8,6 +8,8 @@ import ( "cosmossdk.io/depinject/appconfig" "github.com/cosmos/cosmos-sdk/codec" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" "github.com/node101-io/pulsar-chain/x/votepersistence/types" @@ -33,8 +35,10 @@ type ModuleInputs struct { Cdc codec.Codec AddressCodec address.Codec - AuthKeeper types.AuthKeeper - BankKeeper types.BankKeeper + AuthKeeper types.AuthKeeper + BankKeeper types.BankKeeper + StakingKeeper *stakingkeeper.Keeper + KeyregistryKeeper keyregistrykeeper.Keeper } type ModuleOutputs struct { @@ -54,6 +58,8 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.StoreService, in.Cdc, in.AddressCodec, + in.StakingKeeper, + in.KeyregistryKeeper, authority, ) m := NewAppModule(in.Cdc, k, in.AuthKeeper, in.BankKeeper) diff --git a/x/votepersistence/types/expected_keepers.go b/x/votepersistence/types/expected_keepers.go index b175461c..2d71efd9 100644 --- a/x/votepersistence/types/expected_keepers.go +++ b/x/votepersistence/types/expected_keepers.go @@ -5,6 +5,7 @@ import ( "cosmossdk.io/core/address" sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) // AuthKeeper defines the expected interface for the Auth module. @@ -20,6 +21,15 @@ type BankKeeper interface { // Methods imported from bank should be defined here } +type StakingKeeper interface { + GetHistoricalInfo(context.Context, int64) (stakingtypes.HistoricalInfo, error) +} + +type KeyregistryKeeper interface { + ValidatorCosmosToMinaHas(context.Context, []byte) (bool, error) + ValidatorGetCosmosToMina(context.Context, []byte) ([]byte, error) +} + // ParamSubspace defines the expected Subspace interface for parameters. type ParamSubspace interface { Get(context.Context, []byte, interface{}) From 946b385757e7be1c8ef12c1586905e5ffe3d4554 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Thu, 30 Apr 2026 22:37:57 +0300 Subject: [PATCH 22/63] feat: implement a script to run the chain for vote extension to work as expected --- scripts/derive_mina_pub.go | 31 ++++++ scripts/setup_local_testnet.sh | 115 ++++++++++++++++++++++ scripts/setup_local_testnet_helper.py | 132 ++++++++++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 scripts/derive_mina_pub.go create mode 100755 scripts/setup_local_testnet.sh create mode 100644 scripts/setup_local_testnet_helper.py diff --git a/scripts/derive_mina_pub.go b/scripts/derive_mina_pub.go new file mode 100644 index 00000000..a7da84ca --- /dev/null +++ b/scripts/derive_mina_pub.go @@ -0,0 +1,31 @@ +package main + +import ( + "encoding/base64" + "fmt" + "math/big" + "os" + + "github.com/node101-io/mina-signer-go/keys" +) + +func main() { + if len(os.Args) != 2 { + panic("usage: derive_mina_pub.go ") + } + + privB64 := os.Args[1] + keyBytes, err := base64.StdEncoding.DecodeString(privB64) + if err != nil { + panic(err) + } + + priv := keys.PrivateKey{Value: new(big.Int).SetBytes(keyBytes)} + pub := priv.ToPublicKey() + bz, err := pub.Marshal() + if err != nil { + panic(err) + } + + fmt.Print(base64.StdEncoding.EncodeToString(bz)) +} diff --git a/scripts/setup_local_testnet.sh b/scripts/setup_local_testnet.sh new file mode 100755 index 00000000..6873e6e3 --- /dev/null +++ b/scripts/setup_local_testnet.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd)" +PYTHON_HELPER="$SCRIPT_DIR/setup_local_testnet_helper.py" +GO_HELPER="$SCRIPT_DIR/derive_mina_pub.go" + +CHAIN_HOME="${CHAIN_HOME:-$HOME/.pulsar-chain}" +CHAIN_ID="${CHAIN_ID:-mytestnet}" +MONIKER="${MONIKER:-mynode}" +KEY_NAME="${KEY_NAME:-alice}" +KEYRING_BACKEND="${KEYRING_BACKEND:-test}" +DENOM="${DENOM:-pmina}" +GENESIS_BALANCE="${GENESIS_BALANCE:-1000000000}" +BOND_AMOUNT="${BOND_AMOUNT:-100000000}" +MIN_GAS_PRICE="${MIN_GAS_PRICE:-0.0001pmina}" +VOTE_EXT_ENABLE_HEIGHT="${VOTE_EXT_ENABLE_HEIGHT:-1}" +CONFIG_YML_PATH="${CONFIG_YML_PATH:-$REPO_ROOT/config.yml}" +TMP_BUILD_DIR="$(mktemp -d "${TMPDIR:-/tmp}/pulsar-localnet.XXXXXX")" +BINARY_PATH="$TMP_BUILD_DIR/pulsar-chaind" + +cleanup() { + rm -rf "$TMP_BUILD_DIR" +} + +trap cleanup EXIT + +require_cmd() { + if ! command -v "$1" >/dev/null 2>&1; then + echo "missing required command: $1" >&2 + exit 1 + fi +} + +get_mina_priv_key() { + if [[ -n "${MINA_PRIV_KEY:-}" ]]; then + printf '%s\n' "$MINA_PRIV_KEY" + return + fi + + python3 "$PYTHON_HELPER" read-mina-priv-key --config "$CONFIG_YML_PATH" +} + +derive_mina_pub_key() { + go run "$GO_HELPER" "$1" +} + +require_cmd go +require_cmd python3 + +MINA_PRIV_KEY="$(get_mina_priv_key)" +MINA_PUB_KEY="$(derive_mina_pub_key "$MINA_PRIV_KEY")" + +GENESIS_FILE="$CHAIN_HOME/config/genesis.json" +APP_FILE="$CHAIN_HOME/config/app.toml" + +echo "==> Cleaning previous homes..." +rm -rf "$CHAIN_HOME" "$HOME/.pulsar-node1" "$HOME/.pulsar-node2" + +echo "==> Building temporary binary..." +( + cd "$REPO_ROOT" + go build -o "$BINARY_PATH" ./cmd/pulsard +) + +echo "==> Initializing chain home..." +"$BINARY_PATH" init "$MONIKER" --chain-id "$CHAIN_ID" --home "$CHAIN_HOME" >/dev/null + +echo "==> Setting vote extension enable height..." +python3 "$PYTHON_HELPER" set-vote-extension-height \ + --genesis "$GENESIS_FILE" \ + --height "$VOTE_EXT_ENABLE_HEIGHT" + +echo "==> Creating validator key..." +"$BINARY_PATH" keys add "$KEY_NAME" --home "$CHAIN_HOME" --keyring-backend "$KEYRING_BACKEND" >/dev/null + +VALIDATOR_ADDR="$("$BINARY_PATH" keys show "$KEY_NAME" --address --home "$CHAIN_HOME" --keyring-backend "$KEYRING_BACKEND")" + +echo "==> Adding genesis account for $KEY_NAME..." +"$BINARY_PATH" genesis add-genesis-account "$VALIDATOR_ADDR" "${GENESIS_BALANCE}${DENOM}" --home "$CHAIN_HOME" >/dev/null + +echo "==> Creating gentx..." +"$BINARY_PATH" genesis gentx "$KEY_NAME" "${BOND_AMOUNT}${DENOM}" \ + --chain-id "$CHAIN_ID" \ + --home "$CHAIN_HOME" \ + --keyring-backend "$KEYRING_BACKEND" >/dev/null + +echo "==> Collecting gentxs..." +"$BINARY_PATH" genesis collect-gentxs --home "$CHAIN_HOME" >/dev/null + +echo "==> Patching keyregistry validator key pair from genesis validator pubkey..." +COSMOS_PUB_KEY="$(python3 "$PYTHON_HELPER" patch-keyregistry \ + --genesis "$GENESIS_FILE" \ + --mina-pub-key "$MINA_PUB_KEY")" + +echo "==> Writing vote extension private key to app.toml..." +python3 "$PYTHON_HELPER" update-app-config \ + --app "$APP_FILE" \ + --min-gas-price "$MIN_GAS_PRICE" \ + --mina-priv-key "$MINA_PRIV_KEY" + +echo "==> Validating final genesis..." +"$BINARY_PATH" genesis validate-genesis --home "$CHAIN_HOME" >/dev/null + +echo "" +echo "Setup complete." +echo " home: $CHAIN_HOME" +echo " validator: $KEY_NAME" +echo " cosmos_key: $COSMOS_PUB_KEY" +echo " mina_key: $MINA_PUB_KEY" +echo "" +echo "==> Starting chain..." +"$BINARY_PATH" start --home "$CHAIN_HOME" diff --git a/scripts/setup_local_testnet_helper.py b/scripts/setup_local_testnet_helper.py new file mode 100644 index 00000000..b86818fc --- /dev/null +++ b/scripts/setup_local_testnet_helper.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 + +import argparse +import json +import re +import sys +from pathlib import Path + + +def read_text(path_str: str) -> str: + return Path(path_str).read_text(encoding="utf-8") + + +def write_text(path_str: str, content: str) -> None: + Path(path_str).write_text(content, encoding="utf-8") + + +def read_json(path_str: str): + return json.loads(read_text(path_str)) + + +def write_json(path_str: str, payload) -> None: + write_text(path_str, json.dumps(payload, indent=2) + "\n") + + +def read_mina_priv_key(config_path: str) -> int: + content = read_text(config_path) + match = re.search(r'vote_extension:\s*\n\s*priv_key:\s*"([^"]+)"', content) + if not match: + raise SystemExit( + f"could not find validators[].app.vote_extension.priv_key in {config_path}" + ) + + print(match.group(1)) + return 0 + + +def set_vote_extension_height(genesis_path: str, height: str) -> int: + genesis = read_json(genesis_path) + genesis["consensus"]["params"]["abci"]["vote_extensions_enable_height"] = height + write_json(genesis_path, genesis) + return 0 + + +def patch_keyregistry(genesis_path: str, mina_pub_key: str) -> int: + genesis = read_json(genesis_path) + + cosmos_pub_key = ( + genesis["app_state"]["genutil"]["gen_txs"][0]["body"]["messages"][0]["pubkey"]["key"] + ) + + keyregistry = genesis["app_state"].setdefault("keyregistry", {}) + keyregistry["params"] = keyregistry.get("params", {}) + keyregistry["user_key_pairs"] = [] + keyregistry["validator_key_pairs"] = [ + { + "cosmos_key": cosmos_pub_key, + "mina_key": mina_pub_key, + } + ] + + write_json(genesis_path, genesis) + print(cosmos_pub_key) + return 0 + + +def update_app_config(app_path: str, min_gas_price: str, mina_priv_key: str) -> int: + app_toml = read_text(app_path) + app_toml = app_toml.replace( + 'minimum-gas-prices = ""', + f'minimum-gas-prices = "{min_gas_price}"', + 1, + ) + + vote_extension_block = f'[vote_extension]\npriv_key = "{mina_priv_key}"\n' + + if "\n[vote_extension]\n" in app_toml: + start = app_toml.index("\n[vote_extension]\n") + 1 + end = app_toml.find("\n[", start + 1) + if end == -1: + app_toml = app_toml[:start] + vote_extension_block + else: + app_toml = app_toml[:start] + vote_extension_block + app_toml[end + 1 :] + else: + app_toml = app_toml.rstrip() + f"\n\n{vote_extension_block}" + + write_text(app_path, app_toml) + return 0 + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="Helpers for local testnet setup.") + subparsers = parser.add_subparsers(dest="command", required=True) + + read_key = subparsers.add_parser("read-mina-priv-key") + read_key.add_argument("--config", required=True) + + set_height = subparsers.add_parser("set-vote-extension-height") + set_height.add_argument("--genesis", required=True) + set_height.add_argument("--height", required=True) + + patch_registry = subparsers.add_parser("patch-keyregistry") + patch_registry.add_argument("--genesis", required=True) + patch_registry.add_argument("--mina-pub-key", required=True) + + update_app = subparsers.add_parser("update-app-config") + update_app.add_argument("--app", required=True) + update_app.add_argument("--min-gas-price", required=True) + update_app.add_argument("--mina-priv-key", required=True) + + return parser + + +def main() -> int: + parser = build_parser() + args = parser.parse_args() + + if args.command == "read-mina-priv-key": + return read_mina_priv_key(args.config) + if args.command == "set-vote-extension-height": + return set_vote_extension_height(args.genesis, args.height) + if args.command == "patch-keyregistry": + return patch_keyregistry(args.genesis, args.mina_pub_key) + if args.command == "update-app-config": + return update_app_config(args.app, args.min_gas_price, args.mina_priv_key) + + parser.print_help(sys.stderr) + return 1 + + +if __name__ == "__main__": + raise SystemExit(main()) From 128f10067ba41454cefbe6a437df7ff0e0a65a20 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Thu, 30 Apr 2026 22:39:34 +0300 Subject: [PATCH 23/63] fix: prevent query requests for blocks bigger than the current block --- x/votepersistence/keeper/query_vote_ext_body_by_height.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/votepersistence/keeper/query_vote_ext_body_by_height.go b/x/votepersistence/keeper/query_vote_ext_body_by_height.go index 5bfcf446..2c599011 100644 --- a/x/votepersistence/keeper/query_vote_ext_body_by_height.go +++ b/x/votepersistence/keeper/query_vote_ext_body_by_height.go @@ -28,8 +28,8 @@ func (q queryServer) VoteExtBodyByHeight(ctx context.Context, req *types.QueryVo sdkCtx := sdk.UnwrapSDKContext(ctx) - if req.BlockHeight == sdkCtx.BlockHeight() { - return nil, status.Error(codes.InvalidArgument, "no vote extensions in this block yet") + if req.BlockHeight >= sdkCtx.BlockHeight() { + return nil, status.Error(codes.InvalidArgument, "no vote extensions in the requested block yet") } if q.k.stakingKeeper == nil || q.k.keyregistryKeeper == nil { From 4f187b78fe30a81c51f7f8ffea2187334038d286 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 16:14:50 +0300 Subject: [PATCH 24/63] chore: add a helper to extract payload and simplify function signatures accordingly --- abci/helpers.go | 31 ++++++++++++------------------- abci/pre_blocker.go | 9 +-------- abci/process_proposal.go | 9 +++++++-- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/abci/helpers.go b/abci/helpers.go index cab16eb4..faf792d7 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -44,24 +44,28 @@ func MockSignatureVerify(signature []byte, message VoteExtensionBody, minaKey [] return true } -func (h *AbciHandler) verifyVoteExtension(ctx context.Context, txs [][]byte, body VoteExtensionBody) error { +func extractPayload(txs [][]byte) (payload, error) { voteExtensionTx := txs[0] if !strings.Contains(string(txs[0]), VoteExtMarker) { - return types.ErrVoteExtMarkerNotFound + return payload{}, types.ErrVoteExtMarkerNotFound } voteExtensionTx = voteExtensionTx[len([]byte(VoteExtMarker)):] - var payload payload + var pl payload - err := json.Unmarshal(voteExtensionTx, &payload) + err := json.Unmarshal(voteExtensionTx, &pl) if err != nil { - return err + return payload{}, err } + return pl, nil +} + +func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl payload, body VoteExtensionBody) error { - for publicKey, vote := range payload.Votes { + for publicKey, vote := range pl.Votes { pk, err := hex.DecodeString(publicKey) if err != nil { @@ -208,7 +212,7 @@ func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []valid } -func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, txs [][]byte) (bool, error) { +func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl payload) (bool, error) { var signedStakePower int64 var currentValidatorStakePower int64 @@ -231,18 +235,7 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, txs [] currentValidatorStakePower += val.Power } - voteExtensionTx := txs[0] - - voteExtensionTx = voteExtensionTx[len([]byte(VoteExtMarker)):] - - var payload payload - - err = json.Unmarshal(voteExtensionTx, &payload) - if err != nil { - return false, err - } - - for addr := range payload.Votes { + for addr := range pl.Votes { validatorInfo, ok := valInfoMap[addr] if ok { signedStakePower += validatorInfo.Power diff --git a/abci/pre_blocker.go b/abci/pre_blocker.go index a00365c5..0bc8264c 100644 --- a/abci/pre_blocker.go +++ b/abci/pre_blocker.go @@ -2,7 +2,6 @@ package vote_ext import ( "encoding/hex" - "encoding/json" "fmt" abci "github.com/cometbft/cometbft/abci/types" @@ -22,13 +21,7 @@ func (h *AbciHandler) PreBlocker() sdk.PreBlocker { return nil, err } - voteExtensionTx := req.Txs[0] - - voteExtensionTx = voteExtensionTx[len([]byte(VoteExtMarker)):] - - var pl payload - - err = json.Unmarshal(voteExtensionTx, &pl) + pl, err := extractPayload(req.Txs) if err != nil { return nil, err } diff --git a/abci/process_proposal.go b/abci/process_proposal.go index 6d239e07..a46b1f5f 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -21,12 +21,17 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } - err = h.verifyVoteExtension(ctx, req.Txs, body) + pl, err := extractPayload(req.Txs) if err != nil { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } - isEnoughStakePower, err := h.checkStakePower(ctx, req.GetHeight(), req.Txs) + err = h.verifyVoteExtension(ctx, pl, body) + if err != nil { + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err + } + + isEnoughStakePower, err := h.checkStakePower(ctx, req.GetHeight(), pl) if err != nil { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } From 2e1439ebe2f253c5aed2fbce3453363f472a3272 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 16:23:55 +0300 Subject: [PATCH 25/63] chore: rename newvoteextensionhandler to newabcihandler and move it to handler.go --- abci/extend_vote.go | 10 ---------- abci/handler.go | 30 ++++++++++++++++++++++++++++++ abci/helpers.go | 18 ------------------ app/app.go | 2 +- 4 files changed, 31 insertions(+), 29 deletions(-) create mode 100644 abci/handler.go diff --git a/abci/extend_vote.go b/abci/extend_vote.go index 2cf27b64..d7dba24d 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -3,9 +3,6 @@ package vote_ext import ( abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" - votepersistence "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" ) const ActionsReducedRoot string = "pulsar" @@ -21,13 +18,6 @@ type VoteExtensionBody struct { CurrentBlockHeight int64 } -type AbciHandler struct { - secondaryKey SecondaryKey - stakingKeeper stakingkeeper.Keeper - keyregistryKeeper keyregistrykeeper.Keeper - votePersistenceKeeper votepersistence.Keeper -} - func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return func(ctx sdk.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) { diff --git a/abci/handler.go b/abci/handler.go new file mode 100644 index 00000000..4ce74ec8 --- /dev/null +++ b/abci/handler.go @@ -0,0 +1,30 @@ +package vote_ext + +import ( + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/node101-io/mina-signer-go/keys" + keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" + votepersistence "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" +) + +type SecondaryKey struct { + SecretKey *keys.PrivateKey + PublicKey *keys.PublicKey +} + +type AbciHandler struct { + secondaryKey SecondaryKey + stakingKeeper stakingkeeper.Keeper + keyregistryKeeper keyregistrykeeper.Keeper + votePersistenceKeeper votepersistence.Keeper +} + +func NewABCIHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Keeper, + keyregistryKeeper keyregistrykeeper.Keeper, votepersistenceKeeper votepersistence.Keeper) *AbciHandler { + return &AbciHandler{ + secondaryKey: secondaryKey, + stakingKeeper: stakingKeeper, + keyregistryKeeper: keyregistryKeeper, + votePersistenceKeeper: votepersistenceKeeper, + } +} diff --git a/abci/helpers.go b/abci/helpers.go index faf792d7..f160d9af 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -10,32 +10,14 @@ import ( abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/node101-io/mina-signer-go/constants" "github.com/node101-io/mina-signer-go/field" "github.com/node101-io/mina-signer-go/keys" "github.com/node101-io/mina-signer-go/poseidon" - keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" - votepersistence "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" "github.com/node101-io/pulsar-chain/x/votepersistence/types" ) -type SecondaryKey struct { - SecretKey *keys.PrivateKey - PublicKey *keys.PublicKey -} - -func NewVoteExtHandler(secondaryKey SecondaryKey, stakingKeeper stakingkeeper.Keeper, - keyregistryKeeper keyregistrykeeper.Keeper, votepersistenceKeeper votepersistence.Keeper) *AbciHandler { - return &AbciHandler{ - secondaryKey: secondaryKey, - stakingKeeper: stakingKeeper, - keyregistryKeeper: keyregistryKeeper, - votePersistenceKeeper: votepersistenceKeeper, - } -} - func MockSign(voteExtBody VoteExtensionBody) []byte { return []byte{} } diff --git a/app/app.go b/app/app.go index acc1ab20..122cbc6f 100644 --- a/app/app.go +++ b/app/app.go @@ -221,7 +221,7 @@ func New( PublicKey: &public, } - app.AbciHandler = vote_ext.NewVoteExtHandler( + app.AbciHandler = vote_ext.NewABCIHandler( secondaryKey, *app.StakingKeeper, app.KeyregistryKeeper, From 9b5f498f11c7810f127e971387815de575551070 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 16:25:51 +0300 Subject: [PATCH 26/63] chore: add actions reduced root field to vote extension body --- abci/extend_vote.go | 1 + abci/helpers.go | 2 ++ 2 files changed, 3 insertions(+) diff --git a/abci/extend_vote.go b/abci/extend_vote.go index d7dba24d..c917422c 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -16,6 +16,7 @@ type VoteExtensionBody struct { NextValidatorSetHash []byte CurrentStateRoot []byte CurrentBlockHeight int64 + ActionsReducedRoot string } func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { diff --git a/abci/helpers.go b/abci/helpers.go index f160d9af..a92ff159 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -256,6 +256,7 @@ func (h *AbciHandler) constructVoteExtBody(ctx sdk.Context, blockHeight int64) ( NextValidatorSetHash: nextValidatorSetHash.Bytes(), CurrentStateRoot: currentBlockInfo.Header.AppHash, CurrentBlockHeight: blockHeight - 1, + ActionsReducedRoot: ActionsReducedRoot, }, nil } @@ -285,6 +286,7 @@ func (h *AbciHandler) reconstructVoteExtBody(ctx sdk.Context, blockHeight int64) NextValidatorSetHash: nextValidatorSetHash.Bytes(), CurrentStateRoot: currentBlockInfo.Header.AppHash, CurrentBlockHeight: blockHeight - 1, + ActionsReducedRoot: ActionsReducedRoot, }, nil } From 2813c566652a0da89790c9388a7e1dd5aa8aa831 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 16:35:01 +0300 Subject: [PATCH 27/63] chore: create types folder and move constants and payload struct to there --- abci/helpers.go | 22 +++++++++++----------- abci/prepare_proposal.go | 7 ------- abci/types.go | 10 ++++++++++ 3 files changed, 21 insertions(+), 18 deletions(-) create mode 100644 abci/types.go diff --git a/abci/helpers.go b/abci/helpers.go index a92ff159..de3a9362 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -26,26 +26,26 @@ func MockSignatureVerify(signature []byte, message VoteExtensionBody, minaKey [] return true } -func extractPayload(txs [][]byte) (payload, error) { +func extractPayload(txs [][]byte) (Payload, error) { voteExtensionTx := txs[0] if !strings.Contains(string(txs[0]), VoteExtMarker) { - return payload{}, types.ErrVoteExtMarkerNotFound + return Payload{}, types.ErrVoteExtMarkerNotFound } voteExtensionTx = voteExtensionTx[len([]byte(VoteExtMarker)):] - var pl payload + var pl Payload err := json.Unmarshal(voteExtensionTx, &pl) if err != nil { - return payload{}, err + return Payload{}, err } return pl, nil } -func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl payload, body VoteExtensionBody) error { +func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl Payload, body VoteExtensionBody) error { for publicKey, vote := range pl.Votes { @@ -194,7 +194,7 @@ func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []valid } -func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl payload) (bool, error) { +func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl Payload) (bool, error) { var signedStakePower int64 var currentValidatorStakePower int64 @@ -304,13 +304,13 @@ func (h *AbciHandler) getValidatorPublicKey(ctx sdk.Context, validatorAddr []byt return cosmosValidatorPubKey.Bytes(), nil } -func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteExtensions []abci.ExtendedVoteInfo) (payload, error) { +func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteExtensions []abci.ExtendedVoteInfo) (Payload, error) { voteExtsForGivenBlock := make(map[string][]byte) currentValidatorSetMap := make(map[string]bool) currentValidatorSet, err := h.getHistoricalValidatorSet(ctx, blockHeight-2) if err != nil { - return payload{}, err + return Payload{}, err } for _, currentValidator := range currentValidatorSet { @@ -325,15 +325,15 @@ func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteE cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, vote.Validator.Address) if err != nil { - return payload{}, err + return Payload{}, err } voteExtsForGivenBlock[hex.EncodeToString(cosmosValidatorPubKey)] = voteExtensions[i].VoteExtension } if len(voteExtsForGivenBlock) == 0 { - return payload{}, nil + return Payload{}, nil } - return payload{Height: blockHeight - 1, Votes: voteExtsForGivenBlock}, nil + return Payload{Height: blockHeight - 1, Votes: voteExtsForGivenBlock}, nil } diff --git a/abci/prepare_proposal.go b/abci/prepare_proposal.go index aa6f85ee..5a6a83b8 100644 --- a/abci/prepare_proposal.go +++ b/abci/prepare_proposal.go @@ -7,13 +7,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -var VoteExtMarker string = "VOTEEXT:" - -type payload struct { - Height int64 `json:"height"` - Votes map[string][]byte `json:"votes"` -} - func (h *AbciHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) { diff --git a/abci/types.go b/abci/types.go new file mode 100644 index 00000000..2db9b0ac --- /dev/null +++ b/abci/types.go @@ -0,0 +1,10 @@ +package vote_ext + +const ActionsReducedRoot string = "pulsar" + +var VoteExtMarker string = "VOTEEXT:" + +type Payload struct { + Height int64 `json:"height"` + Votes map[string][]byte `json:"votes"` +} From 301bfd91014dca5b589c70498cfbaa7d9ab723a4 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 17:14:57 +0300 Subject: [PATCH 28/63] chore: unify construct and reconstruct vote ext body functions, and remove reconstruct vote ext body helper --- abci/extend_vote.go | 2 - abci/helpers.go | 100 +++++++++++++-------------------------- abci/pre_blocker.go | 2 +- abci/process_proposal.go | 2 +- 4 files changed, 35 insertions(+), 71 deletions(-) diff --git a/abci/extend_vote.go b/abci/extend_vote.go index c917422c..045d153d 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -5,8 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -const ActionsReducedRoot string = "pulsar" - type validatorInfo struct { ConsensusAddr []byte Power int64 diff --git a/abci/helpers.go b/abci/helpers.go index de3a9362..a024479d 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -77,7 +77,36 @@ func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl Payload, body } // Use if you need the validator set of block < N where N is the current block number. -func (h *AbciHandler) getHistoricalValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]validatorInfo, error) { +func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]validatorInfo, error) { + + var valInfo []validatorInfo + var iterErr error + + if ctx.BlockHeight() == currentBlockHeight { + err := h.stakingKeeper.IterateLastValidators(ctx, func(index int64, validator stakingTypes.ValidatorI) (stop bool) { + consAddr, err := validator.GetConsAddr() + if err != nil { + iterErr = err + return true + } + + valInfo = append(valInfo, validatorInfo{ + ConsensusAddr: consAddr, + Power: validator.GetConsensusPower(sdk.DefaultPowerReduction), + }) + + return false + }) + + if err != nil { + return nil, err + } + if iterErr != nil { + return nil, iterErr + } + + return valInfo, nil + } historicalData, err := h.stakingKeeper.GetHistoricalInfo(ctx, currentBlockHeight) if err != nil { @@ -86,8 +115,6 @@ func (h *AbciHandler) getHistoricalValidatorSet(ctx sdk.Context, currentBlockHei validatorSet := historicalData.Valset - var valInfo []validatorInfo - for _, validator := range validatorSet { consAddr, err := validator.GetConsAddr() @@ -105,37 +132,6 @@ func (h *AbciHandler) getHistoricalValidatorSet(ctx sdk.Context, currentBlockHei return valInfo, nil } -// Use if you need the validator set of the current block -func (h *AbciHandler) getCurrentValidatorSet(ctx sdk.Context) ([]validatorInfo, error) { - - var valInfo []validatorInfo - var iterErr error - - err := h.stakingKeeper.IterateLastValidators(ctx, func(index int64, validator stakingTypes.ValidatorI) (stop bool) { - consAddr, err := validator.GetConsAddr() - if err != nil { - iterErr = err - return true - } - - valInfo = append(valInfo, validatorInfo{ - ConsensusAddr: consAddr, - Power: validator.GetConsensusPower(sdk.DefaultPowerReduction), - }) - - return false - }) - - if err != nil { - return nil, err - } - if iterErr != nil { - return nil, iterErr - } - - return valInfo, nil -} - // TODO: Move this helper to mina-signer-go func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []validatorInfo, poseidonHash *poseidon.Poseidon) (*big.Int, error) { @@ -200,7 +196,7 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl Pay valInfoMap := make(map[string]validatorInfo) - currentValidatorSet, err := h.getHistoricalValidatorSet(ctx, blockHeight-2) + currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) if err != nil { return false, err } @@ -232,37 +228,7 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl Pay func (h *AbciHandler) constructVoteExtBody(ctx sdk.Context, blockHeight int64) (VoteExtensionBody, error) { - nextValidatorSet, err := h.getCurrentValidatorSet(ctx) - if err != nil { - return VoteExtensionBody{}, err - } - - currentBlockInfo, err := h.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-1) - if err != nil { - return VoteExtensionBody{}, err - } - - poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) - - nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, nextValidatorSet, poseidonHash) - if err != nil { - return VoteExtensionBody{}, err - } - if nextValidatorSetHash == nil { - return VoteExtensionBody{}, err - } - - return VoteExtensionBody{ - NextValidatorSetHash: nextValidatorSetHash.Bytes(), - CurrentStateRoot: currentBlockInfo.Header.AppHash, - CurrentBlockHeight: blockHeight - 1, - ActionsReducedRoot: ActionsReducedRoot, - }, nil -} - -func (h *AbciHandler) reconstructVoteExtBody(ctx sdk.Context, blockHeight int64) (VoteExtensionBody, error) { - - nextValidatorSet, err := h.getHistoricalValidatorSet(ctx, blockHeight) + nextValidatorSet, err := h.getValidatorSet(ctx, blockHeight) if err != nil { return VoteExtensionBody{}, err } @@ -308,7 +274,7 @@ func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteE voteExtsForGivenBlock := make(map[string][]byte) currentValidatorSetMap := make(map[string]bool) - currentValidatorSet, err := h.getHistoricalValidatorSet(ctx, blockHeight-2) + currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) if err != nil { return Payload{}, err } diff --git a/abci/pre_blocker.go b/abci/pre_blocker.go index 0bc8264c..c9deab13 100644 --- a/abci/pre_blocker.go +++ b/abci/pre_blocker.go @@ -26,7 +26,7 @@ func (h *AbciHandler) PreBlocker() sdk.PreBlocker { return nil, err } - currentValidatorSet, err := h.getHistoricalValidatorSet(ctx, req.GetHeight()-2) + currentValidatorSet, err := h.getValidatorSet(ctx, req.GetHeight()-2) if err != nil { return nil, err } diff --git a/abci/process_proposal.go b/abci/process_proposal.go index a46b1f5f..9f459434 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -16,7 +16,7 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil } - body, err := h.reconstructVoteExtBody(ctx, req.GetHeight()-1) + body, err := h.constructVoteExtBody(ctx, req.GetHeight()-1) if err != nil { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } From 2dbfef73fb500a96e8fbf9d26c24dbf398383c42 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 17:20:49 +0300 Subject: [PATCH 29/63] fix: handle empty block error --- abci/helpers.go | 4 ++++ abci/types.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/abci/helpers.go b/abci/helpers.go index a024479d..38972196 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -28,6 +28,10 @@ func MockSignatureVerify(signature []byte, message VoteExtensionBody, minaKey [] func extractPayload(txs [][]byte) (Payload, error) { + if len(txs) == 0 { + return Payload{}, ErrEmptyBlock + } + voteExtensionTx := txs[0] if !strings.Contains(string(txs[0]), VoteExtMarker) { diff --git a/abci/types.go b/abci/types.go index 2db9b0ac..1a76b191 100644 --- a/abci/types.go +++ b/abci/types.go @@ -1,9 +1,13 @@ package vote_ext +import "errors" + const ActionsReducedRoot string = "pulsar" var VoteExtMarker string = "VOTEEXT:" +var ErrEmptyBlock error = errors.New("this block has no transaction") + type Payload struct { Height int64 `json:"height"` Votes map[string][]byte `json:"votes"` From 78cd2e9ef3baf08c2902a9ca7c82d09366a40dee Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 17:32:15 +0300 Subject: [PATCH 30/63] fix: use vote storage map's clear method instead of remove --- abci/pre_blocker.go | 2 +- x/votepersistence/keeper/keeper.go | 22 ++----------------- x/votepersistence/keeper/vote_storage_test.go | 2 +- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/abci/pre_blocker.go b/abci/pre_blocker.go index c9deab13..363f9eff 100644 --- a/abci/pre_blocker.go +++ b/abci/pre_blocker.go @@ -16,7 +16,7 @@ func (h *AbciHandler) PreBlocker() sdk.PreBlocker { return &sdk.ResponsePreBlock{}, nil } - err := h.votePersistenceKeeper.RemoveVotes(ctx) + err := h.votePersistenceKeeper.Clear(ctx) if err != nil { return nil, err } diff --git a/x/votepersistence/keeper/keeper.go b/x/votepersistence/keeper/keeper.go index 83ac0d67..3cf7666b 100644 --- a/x/votepersistence/keeper/keeper.go +++ b/x/votepersistence/keeper/keeper.go @@ -86,26 +86,8 @@ func (k Keeper) RemoveVote(ctx context.Context, blockHeight int64, minaAddress [ return k.voteStorage.Remove(ctx, collections.Join(blockHeight, minaAddress)) } -func (k Keeper) RemoveVotes(ctx context.Context) error { - - iterator, err := k.voteStorage.Iterate(ctx, nil) - if err != nil { - return err - } - defer iterator.Close() - - for iterator.Valid() { - key, err := iterator.Key() - if err != nil { - return err - } - err = k.voteStorage.Remove(ctx, key) - if err != nil { - return err - } - iterator.Next() - } - return nil +func (k Keeper) Clear(ctx context.Context) error { + return k.voteStorage.Clear(ctx, nil) } func (k Keeper) VoteExists(ctx context.Context, blockHeight int64, minaAddress []byte) (bool, error) { diff --git a/x/votepersistence/keeper/vote_storage_test.go b/x/votepersistence/keeper/vote_storage_test.go index f3e9c2f2..84e2f8ff 100644 --- a/x/votepersistence/keeper/vote_storage_test.go +++ b/x/votepersistence/keeper/vote_storage_test.go @@ -83,7 +83,7 @@ func TestVoteStorageRemoveVotes(t *testing.T) { require.NoError(t, err) } - err := f.keeper.RemoveVotes(f.ctx) + err := f.keeper.Clear(f.ctx) require.NoError(t, err) for _, entry := range entries { From cd96ab1fa9ff856289bfeedd0cd2c34fbf25b34d Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 17:43:44 +0300 Subject: [PATCH 31/63] chore: remove validatorInfo struct and use cosmos sdk's validator struct --- abci/extend_vote.go | 5 ---- abci/helpers.go | 70 +++++++++++++++++++-------------------------- abci/pre_blocker.go | 8 +++++- 3 files changed, 36 insertions(+), 47 deletions(-) diff --git a/abci/extend_vote.go b/abci/extend_vote.go index 045d153d..7dec9fa3 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -5,11 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -type validatorInfo struct { - ConsensusAddr []byte - Power int64 -} - type VoteExtensionBody struct { NextValidatorSetHash []byte CurrentStateRoot []byte diff --git a/abci/helpers.go b/abci/helpers.go index 38972196..75e3d0e0 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -81,33 +81,19 @@ func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl Payload, body } // Use if you need the validator set of block < N where N is the current block number. -func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]validatorInfo, error) { +func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]stakingTypes.ValidatorI, error) { - var valInfo []validatorInfo - var iterErr error + var valInfo []stakingTypes.ValidatorI if ctx.BlockHeight() == currentBlockHeight { err := h.stakingKeeper.IterateLastValidators(ctx, func(index int64, validator stakingTypes.ValidatorI) (stop bool) { - consAddr, err := validator.GetConsAddr() - if err != nil { - iterErr = err - return true - } - - valInfo = append(valInfo, validatorInfo{ - ConsensusAddr: consAddr, - Power: validator.GetConsensusPower(sdk.DefaultPowerReduction), - }) - + valInfo = append(valInfo, validator) return false }) if err != nil { return nil, err } - if iterErr != nil { - return nil, iterErr - } return valInfo, nil } @@ -116,28 +102,14 @@ func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) if err != nil { return nil, err } - - validatorSet := historicalData.Valset - - for _, validator := range validatorSet { - - consAddr, err := validator.GetConsAddr() - if err != nil { - return nil, err - } - - consPower := validator.ConsensusPower(sdk.DefaultPowerReduction) - - valInfo = append(valInfo, validatorInfo{ - ConsensusAddr: consAddr, - Power: consPower, - }) + for _, validator := range historicalData.Valset { + valInfo = append(valInfo, validator) } return valInfo, nil } // TODO: Move this helper to mina-signer-go -func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []validatorInfo, poseidonHash *poseidon.Poseidon) (*big.Int, error) { +func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []stakingTypes.ValidatorI, poseidonHash *poseidon.Poseidon) (*big.Int, error) { input := []*big.Int{big.NewInt(0)} merkleRoot := poseidonHash.Hash(input) @@ -145,7 +117,12 @@ func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []valid for _, validator := range valInfo { input = []*big.Int{} - cosmosValidatorInfo, err := h.stakingKeeper.GetValidatorByConsAddr(ctx, validator.ConsensusAddr) + consAddr, err := validator.GetConsAddr() + if err != nil { + continue + } + + cosmosValidatorInfo, err := h.stakingKeeper.GetValidatorByConsAddr(ctx, consAddr) if err != nil { return nil, err } @@ -180,7 +157,7 @@ func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []valid } else { input = append(input, big.NewInt(0)) } - power := new(big.Int).SetInt64(validator.Power) + power := new(big.Int).SetInt64(validator.GetConsensusPower(sdk.DefaultPowerReduction)) input = append(input, power) hashOfAddr := poseidonHash.Hash(input) @@ -198,7 +175,7 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl Pay var signedStakePower int64 var currentValidatorStakePower int64 - valInfoMap := make(map[string]validatorInfo) + valInfoMap := make(map[string]stakingTypes.ValidatorI) currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) if err != nil { @@ -208,19 +185,24 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl Pay // Require at least 2/3 signed power to prevent proposer-side signature withholding. for _, val := range currentValidatorSet { - cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, val.ConsensusAddr) + consAddr, err := val.GetConsAddr() + if err != nil { + continue + } + + cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, consAddr) if err != nil { return false, err } valInfoMap[hex.EncodeToString(cosmosValidatorPubKey)] = val - currentValidatorStakePower += val.Power + currentValidatorStakePower += val.GetConsensusPower(sdk.DefaultPowerReduction) } for addr := range pl.Votes { validatorInfo, ok := valInfoMap[addr] if ok { - signedStakePower += validatorInfo.Power + signedStakePower += validatorInfo.GetConsensusPower(sdk.DefaultPowerReduction) } } if signedStakePower*3 < currentValidatorStakePower*2 { @@ -284,7 +266,13 @@ func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteE } for _, currentValidator := range currentValidatorSet { - currentValidatorSetMap[string(currentValidator.ConsensusAddr)] = true + + consAddr, err := currentValidator.GetConsAddr() + if err != nil { + continue + } + + currentValidatorSetMap[string(consAddr)] = true } for i, vote := range voteExtensions { diff --git a/abci/pre_blocker.go b/abci/pre_blocker.go index 363f9eff..aab27f7c 100644 --- a/abci/pre_blocker.go +++ b/abci/pre_blocker.go @@ -34,7 +34,13 @@ func (h *AbciHandler) PreBlocker() sdk.PreBlocker { currentValidatorSetMap := make(map[string][]byte) for _, currentValidator := range currentValidatorSet { - cosmosValidatorPublicKey, err := h.getValidatorPublicKey(ctx, currentValidator.ConsensusAddr) + + consAddr, err := currentValidator.GetConsAddr() + if err != nil { + continue + } + + cosmosValidatorPublicKey, err := h.getValidatorPublicKey(ctx, consAddr) if err != nil { return nil, err } From 88177d7dfeab3491d2ba8c5bbd801eccf247eace Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 18:02:55 +0300 Subject: [PATCH 32/63] feat: add sorting by validator power to ensure each node gets the same validator set root --- abci/helpers.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/abci/helpers.go b/abci/helpers.go index 75e3d0e0..23dccf1d 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -1,11 +1,13 @@ package vote_ext import ( + "bytes" "context" "encoding/hex" "encoding/json" "fmt" "math/big" + "sort" "strings" abci "github.com/cometbft/cometbft/abci/types" @@ -94,6 +96,7 @@ func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) if err != nil { return nil, err } + sortValidatorsByPower(valInfo) return valInfo, nil } @@ -105,9 +108,34 @@ func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) for _, validator := range historicalData.Valset { valInfo = append(valInfo, validator) } + + sortValidatorsByPower(valInfo) + return valInfo, nil } +func sortValidatorsByPower(validators []stakingTypes.ValidatorI) { + sort.SliceStable(validators, func(i, j int) bool { + leftPower := validators[i].GetConsensusPower(sdk.DefaultPowerReduction) + rightPower := validators[j].GetConsensusPower(sdk.DefaultPowerReduction) + + if leftPower == rightPower { + leftAddr, err := validators[i].GetConsAddr() + if err != nil { + return false + } + rightAddr, err := validators[j].GetConsAddr() + if err != nil { + return false + } + + return bytes.Compare(leftAddr, rightAddr) == -1 + } + + return leftPower > rightPower + }) +} + // TODO: Move this helper to mina-signer-go func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []stakingTypes.ValidatorI, poseidonHash *poseidon.Poseidon) (*big.Int, error) { From 60210fcc6b559254ce4458912a7d95b1f9a4da1d Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 19:09:25 +0300 Subject: [PATCH 33/63] chore: build vote ext body with proto, and return that in query --- abci/extend_vote.go | 7 - abci/helpers.go | 19 +- .../votepersistence/v1/query.proto | 10 +- .../votepersistence/v1/vote_ext_body.proto | 12 + .../keeper/query_vote_ext_body_by_height.go | 23 +- x/votepersistence/types/query.pb.go | 342 ++----------- x/votepersistence/types/vote_ext_body.pb.go | 467 ++++++++++++++++++ 7 files changed, 538 insertions(+), 342 deletions(-) create mode 100644 proto/pulsarchain/votepersistence/v1/vote_ext_body.proto create mode 100644 x/votepersistence/types/vote_ext_body.pb.go diff --git a/abci/extend_vote.go b/abci/extend_vote.go index 7dec9fa3..776d3a6d 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -5,13 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -type VoteExtensionBody struct { - NextValidatorSetHash []byte - CurrentStateRoot []byte - CurrentBlockHeight int64 - ActionsReducedRoot string -} - func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return func(ctx sdk.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) { diff --git a/abci/helpers.go b/abci/helpers.go index 23dccf1d..2e1c47b2 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -18,13 +18,14 @@ import ( "github.com/node101-io/mina-signer-go/keys" "github.com/node101-io/mina-signer-go/poseidon" "github.com/node101-io/pulsar-chain/x/votepersistence/types" + votepersistenceTypes "github.com/node101-io/pulsar-chain/x/votepersistence/types" ) -func MockSign(voteExtBody VoteExtensionBody) []byte { +func MockSign(voteExtBody votepersistenceTypes.VoteExtBody) []byte { return []byte{} } -func MockSignatureVerify(signature []byte, message VoteExtensionBody, minaKey []byte, reducedRoot string) bool { +func MockSignatureVerify(signature []byte, message votepersistenceTypes.VoteExtBody, minaKey []byte, reducedRoot string) bool { return true } @@ -51,7 +52,7 @@ func extractPayload(txs [][]byte) (Payload, error) { return pl, nil } -func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl Payload, body VoteExtensionBody) error { +func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl Payload, body votepersistenceTypes.VoteExtBody) error { for publicKey, vote := range pl.Votes { @@ -240,29 +241,29 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl Pay return true, nil } -func (h *AbciHandler) constructVoteExtBody(ctx sdk.Context, blockHeight int64) (VoteExtensionBody, error) { +func (h *AbciHandler) constructVoteExtBody(ctx sdk.Context, blockHeight int64) (votepersistenceTypes.VoteExtBody, error) { nextValidatorSet, err := h.getValidatorSet(ctx, blockHeight) if err != nil { - return VoteExtensionBody{}, err + return votepersistenceTypes.VoteExtBody{}, err } currentBlockInfo, err := h.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-1) if err != nil { - return VoteExtensionBody{}, err + return votepersistenceTypes.VoteExtBody{}, err } poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, nextValidatorSet, poseidonHash) if err != nil { - return VoteExtensionBody{}, err + return votepersistenceTypes.VoteExtBody{}, err } if nextValidatorSetHash == nil { - return VoteExtensionBody{}, err + return votepersistenceTypes.VoteExtBody{}, err } - return VoteExtensionBody{ + return votepersistenceTypes.VoteExtBody{ NextValidatorSetHash: nextValidatorSetHash.Bytes(), CurrentStateRoot: currentBlockInfo.Header.AppHash, CurrentBlockHeight: blockHeight - 1, diff --git a/proto/pulsarchain/votepersistence/v1/query.proto b/proto/pulsarchain/votepersistence/v1/query.proto index 6d8ce856..215bd80d 100644 --- a/proto/pulsarchain/votepersistence/v1/query.proto +++ b/proto/pulsarchain/votepersistence/v1/query.proto @@ -7,6 +7,8 @@ import "cosmos/base/query/v1beta1/pagination.proto"; import "gogoproto/gogo.proto"; import "google/api/annotations.proto"; import "pulsarchain/votepersistence/v1/params.proto"; +import "pulsarchain/votepersistence/v1/vote_ext_body.proto"; + option go_package = "github.com/node101-io/pulsar-chain/x/votepersistence/types"; @@ -18,7 +20,7 @@ service Query { } // VoteExtBodyByHeight Queries a list of VoteExtBodyByHeight items. - rpc VoteExtBodyByHeight(QueryVoteExtBodyByHeightRequest) returns (QueryVoteExtBodyByHeightResponse) { + rpc VoteExtBodyByHeight(QueryVoteExtBodyByHeightRequest) returns (VoteExtBody) { option (google.api.http).get = "/node101-io/pulsar-chain/votepersistence/v1/vote_ext_body_by_height/{block_height}"; } } @@ -40,9 +42,3 @@ message QueryVoteExtBodyByHeightRequest { int64 block_height = 1; } -// QueryVoteExtBodyByHeightResponse defines the QueryVoteExtBodyByHeightResponse message. -message QueryVoteExtBodyByHeightResponse { - bytes next_validator_set_hash = 1; - bytes current_state_root = 2; - int64 current_block_height = 3; -} diff --git a/proto/pulsarchain/votepersistence/v1/vote_ext_body.proto b/proto/pulsarchain/votepersistence/v1/vote_ext_body.proto new file mode 100644 index 00000000..a7cf3128 --- /dev/null +++ b/proto/pulsarchain/votepersistence/v1/vote_ext_body.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +package pulsarchain.votepersistence.v1; + +option go_package = "github.com/node101-io/pulsar-chain/x/votepersistence/types"; + +// VoteExtBody defines the VoteExtBody message. +message VoteExtBody { + bytes next_validator_set_hash = 1; + bytes current_state_root = 2; + int64 current_block_height = 3; + string actions_reduced_root = 4; +} diff --git a/x/votepersistence/keeper/query_vote_ext_body_by_height.go b/x/votepersistence/keeper/query_vote_ext_body_by_height.go index 2c599011..b8aea73d 100644 --- a/x/votepersistence/keeper/query_vote_ext_body_by_height.go +++ b/x/votepersistence/keeper/query_vote_ext_body_by_height.go @@ -2,8 +2,6 @@ package keeper import ( "context" - "errors" - "fmt" "math/big" sdk "github.com/cosmos/cosmos-sdk/types" @@ -17,7 +15,9 @@ import ( "google.golang.org/grpc/status" ) -func (q queryServer) VoteExtBodyByHeight(ctx context.Context, req *types.QueryVoteExtBodyByHeightRequest) (*types.QueryVoteExtBodyByHeightResponse, error) { +const ActionsReducedRoot string = "pulsar" + +func (q queryServer) VoteExtBodyByHeight(ctx context.Context, req *types.QueryVoteExtBodyByHeightRequest) (*types.VoteExtBody, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") } @@ -39,15 +39,15 @@ func (q queryServer) VoteExtBodyByHeight(ctx context.Context, req *types.QueryVo return q.constructVoteExtBodyByHeight(ctx, req.BlockHeight) } -func (q queryServer) constructVoteExtBodyByHeight(ctx context.Context, blockHeight int64) (*types.QueryVoteExtBodyByHeightResponse, error) { +func (q queryServer) constructVoteExtBodyByHeight(ctx context.Context, blockHeight int64) (*types.VoteExtBody, error) { currentBlockInfo, err := q.k.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-2) if err != nil { - return nil, wrapHistoricalInfoError(blockHeight, err) + return nil, err } nextBlockInfo, err := q.k.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-1) if err != nil { - return nil, wrapHistoricalInfoError(blockHeight+1, err) + return nil, err } nextValidatorSetHash, err := q.calculateValidatorSetRoot(ctx, nextBlockInfo.Valset) @@ -55,10 +55,11 @@ func (q queryServer) constructVoteExtBodyByHeight(ctx context.Context, blockHeig return nil, err } - return &types.QueryVoteExtBodyByHeightResponse{ + return &types.VoteExtBody{ NextValidatorSetHash: nextValidatorSetHash, CurrentStateRoot: currentBlockInfo.Header.AppHash, CurrentBlockHeight: blockHeight - 1, + ActionsReducedRoot: ActionsReducedRoot, }, nil } @@ -110,11 +111,3 @@ func (q queryServer) calculateValidatorSetRoot(ctx context.Context, validatorSet return merkleRoot.Bytes(), nil } - -func wrapHistoricalInfoError(height int64, err error) error { - if errors.Is(err, stakingtypes.ErrNoHistoricalInfo) { - return status.Errorf(codes.NotFound, "historical info not found for height %d", height) - } - - return status.Error(codes.Internal, fmt.Sprintf("failed to load staking historical info for height %d", height)) -} diff --git a/x/votepersistence/types/query.pb.go b/x/votepersistence/types/query.pb.go index 07721a5a..4fa36cb2 100644 --- a/x/votepersistence/types/query.pb.go +++ b/x/votepersistence/types/query.pb.go @@ -6,6 +6,10 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -15,9 +19,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. @@ -159,72 +160,10 @@ func (m *QueryVoteExtBodyByHeightRequest) GetBlockHeight() int64 { return 0 } -// QueryVoteExtBodyByHeightResponse defines the QueryVoteExtBodyByHeightResponse message. -type QueryVoteExtBodyByHeightResponse struct { - NextValidatorSetHash []byte `protobuf:"bytes,1,opt,name=next_validator_set_hash,json=nextValidatorSetHash,proto3" json:"next_validator_set_hash,omitempty"` - CurrentStateRoot []byte `protobuf:"bytes,2,opt,name=current_state_root,json=currentStateRoot,proto3" json:"current_state_root,omitempty"` - CurrentBlockHeight int64 `protobuf:"varint,3,opt,name=current_block_height,json=currentBlockHeight,proto3" json:"current_block_height,omitempty"` -} - -func (m *QueryVoteExtBodyByHeightResponse) Reset() { *m = QueryVoteExtBodyByHeightResponse{} } -func (m *QueryVoteExtBodyByHeightResponse) String() string { return proto.CompactTextString(m) } -func (*QueryVoteExtBodyByHeightResponse) ProtoMessage() {} -func (*QueryVoteExtBodyByHeightResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_2c9976ecef977273, []int{3} -} -func (m *QueryVoteExtBodyByHeightResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryVoteExtBodyByHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryVoteExtBodyByHeightResponse.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 *QueryVoteExtBodyByHeightResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryVoteExtBodyByHeightResponse.Merge(m, src) -} -func (m *QueryVoteExtBodyByHeightResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryVoteExtBodyByHeightResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryVoteExtBodyByHeightResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryVoteExtBodyByHeightResponse proto.InternalMessageInfo - -func (m *QueryVoteExtBodyByHeightResponse) GetNextValidatorSetHash() []byte { - if m != nil { - return m.NextValidatorSetHash - } - return nil -} - -func (m *QueryVoteExtBodyByHeightResponse) GetCurrentStateRoot() []byte { - if m != nil { - return m.CurrentStateRoot - } - return nil -} - -func (m *QueryVoteExtBodyByHeightResponse) GetCurrentBlockHeight() int64 { - if m != nil { - return m.CurrentBlockHeight - } - return 0 -} - func init() { proto.RegisterType((*QueryParamsRequest)(nil), "pulsarchain.votepersistence.v1.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "pulsarchain.votepersistence.v1.QueryParamsResponse") proto.RegisterType((*QueryVoteExtBodyByHeightRequest)(nil), "pulsarchain.votepersistence.v1.QueryVoteExtBodyByHeightRequest") - proto.RegisterType((*QueryVoteExtBodyByHeightResponse)(nil), "pulsarchain.votepersistence.v1.QueryVoteExtBodyByHeightResponse") } func init() { @@ -232,41 +171,35 @@ func init() { } var fileDescriptor_2c9976ecef977273 = []byte{ - // 529 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xc1, 0x6e, 0xd3, 0x40, - 0x10, 0x8d, 0x1b, 0x11, 0x89, 0x6d, 0x0f, 0xb0, 0x8d, 0x44, 0x15, 0x21, 0xb7, 0xe4, 0x80, 0x50, - 0xa0, 0xde, 0x3a, 0x85, 0x4b, 0x2f, 0xa0, 0x08, 0xa4, 0x72, 0x03, 0xb7, 0xea, 0xa1, 0x17, 0xb3, - 0x76, 0x56, 0xb6, 0x45, 0xb2, 0xe3, 0x7a, 0x27, 0x56, 0x2c, 0xc4, 0x85, 0x2f, 0x40, 0xe2, 0x27, - 0xb8, 0x80, 0xb8, 0xf2, 0x07, 0x3d, 0x56, 0xe2, 0xc2, 0x09, 0xa1, 0x04, 0x89, 0x1f, 0xe0, 0x03, - 0x90, 0xd7, 0x1b, 0xd1, 0x52, 0x42, 0x28, 0x97, 0xc8, 0x7a, 0xf3, 0xde, 0x9b, 0x37, 0x33, 0x1b, - 0xd2, 0x49, 0x47, 0x03, 0xc5, 0xb3, 0x30, 0xe6, 0x89, 0x64, 0x39, 0xa0, 0x48, 0x45, 0xa6, 0x12, - 0x85, 0x42, 0x86, 0x82, 0xe5, 0x2e, 0x3b, 0x1a, 0x89, 0xac, 0x70, 0xd2, 0x0c, 0x10, 0xa8, 0x7d, - 0x8a, 0xeb, 0xfc, 0xc6, 0x75, 0x72, 0xb7, 0x75, 0x95, 0x0f, 0x13, 0x09, 0x4c, 0xff, 0x56, 0x92, - 0x56, 0x27, 0x04, 0x35, 0x04, 0xc5, 0x02, 0xae, 0x44, 0xe5, 0xc5, 0x72, 0x37, 0x10, 0xc8, 0x5d, - 0x96, 0xf2, 0x28, 0x91, 0x1c, 0x13, 0x90, 0x86, 0xdb, 0x8c, 0x20, 0x02, 0xfd, 0xc9, 0xca, 0x2f, - 0x83, 0x5e, 0x8f, 0x00, 0xa2, 0x81, 0x60, 0x3c, 0x4d, 0x18, 0x97, 0x12, 0x50, 0x4b, 0x94, 0xa9, - 0xde, 0x5e, 0x10, 0x3f, 0xe5, 0x19, 0x1f, 0x1a, 0x72, 0xbb, 0x49, 0xe8, 0xd3, 0x32, 0xc2, 0x13, - 0x0d, 0x7a, 0xe2, 0x68, 0x24, 0x14, 0xb6, 0x9f, 0x91, 0xd5, 0x33, 0xa8, 0x4a, 0x41, 0x2a, 0x41, - 0x1f, 0x93, 0x46, 0x25, 0x5e, 0xb3, 0x36, 0xac, 0x5b, 0xcb, 0xdd, 0x9b, 0xce, 0xdf, 0xa7, 0x77, - 0x2a, 0x7d, 0xef, 0xf2, 0xf1, 0x97, 0xf5, 0xda, 0xdb, 0xef, 0x1f, 0x3a, 0x96, 0x67, 0x0c, 0xda, - 0x0f, 0xc9, 0xba, 0xee, 0x70, 0x00, 0x28, 0x1e, 0x8d, 0xb1, 0x07, 0xfd, 0xa2, 0x57, 0xec, 0x8a, - 0x24, 0x8a, 0xd1, 0x84, 0xa0, 0x37, 0xc8, 0x4a, 0x30, 0x80, 0xf0, 0xb9, 0x1f, 0x6b, 0x58, 0xf7, - 0xac, 0x7b, 0xcb, 0x1a, 0xab, 0x98, 0xed, 0x8f, 0x16, 0xd9, 0x98, 0x6f, 0x63, 0x52, 0xdf, 0x23, - 0xd7, 0xa4, 0x18, 0xa3, 0x9f, 0xf3, 0x41, 0xd2, 0xe7, 0x08, 0x99, 0xaf, 0x04, 0xfa, 0x31, 0x57, - 0xb1, 0xb6, 0x5c, 0xf1, 0x9a, 0x65, 0xf9, 0x60, 0x56, 0xdd, 0x13, 0xb8, 0xcb, 0x55, 0x4c, 0xef, - 0x10, 0x1a, 0x8e, 0xb2, 0x4c, 0x48, 0xf4, 0x15, 0x72, 0x14, 0x7e, 0x06, 0x80, 0x6b, 0x4b, 0x5a, - 0x71, 0xc5, 0x54, 0xf6, 0xca, 0x82, 0x07, 0x80, 0x74, 0x8b, 0x34, 0x67, 0xec, 0x33, 0xa1, 0xeb, - 0x3a, 0xf4, 0xcc, 0xa9, 0xf7, 0x2b, 0x7b, 0xf7, 0x7d, 0x9d, 0x5c, 0xd2, 0xd9, 0xe9, 0x3b, 0x8b, - 0x34, 0xaa, 0x4d, 0xd1, 0xee, 0xa2, 0x8d, 0x9e, 0x3f, 0x56, 0x6b, 0xfb, 0x42, 0x9a, 0x6a, 0x29, - 0xed, 0x9d, 0x57, 0x9f, 0xbe, 0xbd, 0x59, 0xba, 0x4b, 0xbb, 0x4c, 0x42, 0x5f, 0xb8, 0x5b, 0xee, - 0x66, 0x02, 0xac, 0xf2, 0xd9, 0x5c, 0xf0, 0x72, 0xe8, 0x0f, 0x8b, 0xac, 0xfe, 0x61, 0xe1, 0xf4, - 0xfe, 0x3f, 0x05, 0x99, 0x7f, 0xf1, 0xd6, 0x83, 0xff, 0x37, 0x30, 0x63, 0x1d, 0xea, 0xb1, 0xf6, - 0xa9, 0x77, 0x91, 0xb1, 0x4a, 0xc8, 0x2f, 0x5f, 0x48, 0x00, 0xfd, 0xc2, 0x0f, 0x0a, 0x73, 0x3b, - 0xf6, 0xe2, 0xf4, 0x25, 0x5f, 0xf6, 0xf6, 0x8f, 0x27, 0xb6, 0x75, 0x32, 0xb1, 0xad, 0xaf, 0x13, - 0xdb, 0x7a, 0x3d, 0xb5, 0x6b, 0x27, 0x53, 0xbb, 0xf6, 0x79, 0x6a, 0xd7, 0x0e, 0x77, 0xa2, 0x04, - 0xe3, 0x51, 0xe0, 0x84, 0x30, 0x9c, 0xdb, 0x77, 0x7c, 0xae, 0x33, 0x16, 0xa9, 0x50, 0x41, 0x43, - 0xff, 0x0f, 0xb7, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0x7d, 0x4c, 0x67, 0xcd, 0x75, 0x04, 0x00, - 0x00, + // 446 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x52, 0xcf, 0x6a, 0x13, 0x41, + 0x18, 0xcf, 0x58, 0x0c, 0x38, 0xf5, 0xe2, 0xb4, 0x07, 0x09, 0xb2, 0xd5, 0x3d, 0x88, 0xa4, 0x74, + 0xc7, 0xdd, 0x7a, 0xea, 0x45, 0x08, 0x0a, 0x7a, 0xd3, 0x50, 0x3c, 0xf4, 0x12, 0x67, 0x37, 0x1f, + 0x9b, 0xc1, 0x64, 0xbe, 0xe9, 0xce, 0x64, 0xc9, 0x22, 0x5e, 0x7c, 0x02, 0xc1, 0x93, 0x6f, 0xe0, + 0x45, 0xf0, 0x31, 0x7a, 0x2c, 0x78, 0xf1, 0xa4, 0x92, 0x08, 0xbe, 0x86, 0x64, 0x66, 0x85, 0xd4, + 0x5a, 0xb7, 0xb9, 0x2c, 0xc3, 0xb7, 0xbf, 0xbf, 0xf3, 0x0d, 0xed, 0xea, 0xe9, 0xd8, 0x88, 0x22, + 0x1b, 0x09, 0xa9, 0x78, 0x89, 0x16, 0x34, 0x14, 0x46, 0x1a, 0x0b, 0x2a, 0x03, 0x5e, 0xc6, 0xfc, + 0x78, 0x0a, 0x45, 0x15, 0xe9, 0x02, 0x2d, 0xb2, 0x60, 0x05, 0x1b, 0xfd, 0x85, 0x8d, 0xca, 0xb8, + 0x73, 0x43, 0x4c, 0xa4, 0x42, 0xee, 0xbe, 0x9e, 0xd2, 0xe9, 0x66, 0x68, 0x26, 0x68, 0x78, 0x2a, + 0x0c, 0x78, 0x2d, 0x5e, 0xc6, 0x29, 0x58, 0x11, 0x73, 0x2d, 0x72, 0xa9, 0x84, 0x95, 0xa8, 0x6a, + 0xec, 0x76, 0x8e, 0x39, 0xba, 0x23, 0x5f, 0x9e, 0xea, 0xe9, 0xad, 0x1c, 0x31, 0x1f, 0x03, 0x17, + 0x5a, 0x72, 0xa1, 0x14, 0x5a, 0x47, 0x31, 0xf5, 0xdf, 0xdd, 0x86, 0xf8, 0x5a, 0x14, 0x62, 0xf2, + 0x07, 0x9c, 0x34, 0x80, 0x97, 0xa3, 0x01, 0xcc, 0xec, 0x20, 0xc5, 0x61, 0xdd, 0x39, 0xdc, 0xa6, + 0xec, 0xf9, 0x32, 0xf6, 0x33, 0x27, 0xd4, 0x87, 0xe3, 0x29, 0x18, 0x1b, 0xbe, 0xa4, 0x5b, 0x67, + 0xa6, 0x46, 0xa3, 0x32, 0xc0, 0x9e, 0xd2, 0xb6, 0x37, 0xbc, 0x49, 0x6e, 0x93, 0x7b, 0x9b, 0xc9, + 0xdd, 0xe8, 0xff, 0x37, 0x16, 0x79, 0x7e, 0xef, 0xda, 0xc9, 0xb7, 0x9d, 0xd6, 0xc7, 0x5f, 0x9f, + 0xbb, 0xa4, 0x5f, 0x0b, 0x84, 0x8f, 0xe8, 0x8e, 0x73, 0x78, 0x81, 0x16, 0x1e, 0xcf, 0x6c, 0x0f, + 0x87, 0x55, 0xaf, 0x7a, 0x02, 0x32, 0x1f, 0xd9, 0x3a, 0x04, 0xbb, 0x43, 0xaf, 0xa7, 0x63, 0xcc, + 0x5e, 0x0d, 0x46, 0x6e, 0xec, 0x3c, 0x37, 0xfa, 0x9b, 0x6e, 0xe6, 0x91, 0xc9, 0x87, 0x0d, 0x7a, + 0xd5, 0xc9, 0xb0, 0x4f, 0x84, 0xb6, 0xbd, 0x1b, 0x4b, 0x9a, 0x52, 0x9d, 0x2f, 0xdc, 0xd9, 0x5f, + 0x8b, 0xe3, 0xaf, 0x23, 0x3c, 0x78, 0xfb, 0xe5, 0xe7, 0xfb, 0x2b, 0x0f, 0x58, 0xc2, 0x15, 0x0e, + 0x21, 0xbe, 0x1f, 0xef, 0x49, 0xe4, 0x5e, 0x67, 0xaf, 0x61, 0x63, 0xec, 0x3b, 0xa1, 0x5b, 0xff, + 0xe8, 0xce, 0x1e, 0x5e, 0x2a, 0xc8, 0xc5, 0xb7, 0xd6, 0xd9, 0x6d, 0x12, 0x58, 0xe1, 0x86, 0x47, + 0xae, 0xc1, 0x21, 0xeb, 0xaf, 0xd3, 0xe0, 0xcc, 0x33, 0x1a, 0xa4, 0x55, 0xbd, 0x1f, 0xfe, 0x7a, + 0x75, 0x5b, 0x6f, 0x7a, 0x87, 0x27, 0xf3, 0x80, 0x9c, 0xce, 0x03, 0xf2, 0x63, 0x1e, 0x90, 0x77, + 0x8b, 0xa0, 0x75, 0xba, 0x08, 0x5a, 0x5f, 0x17, 0x41, 0xeb, 0xe8, 0x20, 0x97, 0x76, 0x34, 0x4d, + 0xa3, 0x0c, 0x27, 0x17, 0xfa, 0xce, 0xce, 0x39, 0xdb, 0x4a, 0x83, 0x49, 0xdb, 0xee, 0xd9, 0xee, + 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xa5, 0xd2, 0x62, 0xd8, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -284,7 +217,7 @@ type QueryClient interface { // Parameters queries the parameters of the module. Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) // VoteExtBodyByHeight Queries a list of VoteExtBodyByHeight items. - VoteExtBodyByHeight(ctx context.Context, in *QueryVoteExtBodyByHeightRequest, opts ...grpc.CallOption) (*QueryVoteExtBodyByHeightResponse, error) + VoteExtBodyByHeight(ctx context.Context, in *QueryVoteExtBodyByHeightRequest, opts ...grpc.CallOption) (*VoteExtBody, error) } type queryClient struct { @@ -304,8 +237,8 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . return out, nil } -func (c *queryClient) VoteExtBodyByHeight(ctx context.Context, in *QueryVoteExtBodyByHeightRequest, opts ...grpc.CallOption) (*QueryVoteExtBodyByHeightResponse, error) { - out := new(QueryVoteExtBodyByHeightResponse) +func (c *queryClient) VoteExtBodyByHeight(ctx context.Context, in *QueryVoteExtBodyByHeightRequest, opts ...grpc.CallOption) (*VoteExtBody, error) { + out := new(VoteExtBody) err := c.cc.Invoke(ctx, "/pulsarchain.votepersistence.v1.Query/VoteExtBodyByHeight", in, out, opts...) if err != nil { return nil, err @@ -318,7 +251,7 @@ type QueryServer interface { // Parameters queries the parameters of the module. Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) // VoteExtBodyByHeight Queries a list of VoteExtBodyByHeight items. - VoteExtBodyByHeight(context.Context, *QueryVoteExtBodyByHeightRequest) (*QueryVoteExtBodyByHeightResponse, error) + VoteExtBodyByHeight(context.Context, *QueryVoteExtBodyByHeightRequest) (*VoteExtBody, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -328,7 +261,7 @@ type UnimplementedQueryServer struct { func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") } -func (*UnimplementedQueryServer) VoteExtBodyByHeight(ctx context.Context, req *QueryVoteExtBodyByHeightRequest) (*QueryVoteExtBodyByHeightResponse, error) { +func (*UnimplementedQueryServer) VoteExtBodyByHeight(ctx context.Context, req *QueryVoteExtBodyByHeightRequest) (*VoteExtBody, error) { return nil, status.Errorf(codes.Unimplemented, "method VoteExtBodyByHeight not implemented") } @@ -474,48 +407,6 @@ func (m *QueryVoteExtBodyByHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int return len(dAtA) - i, nil } -func (m *QueryVoteExtBodyByHeightResponse) 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 *QueryVoteExtBodyByHeightResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryVoteExtBodyByHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.CurrentBlockHeight != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.CurrentBlockHeight)) - i-- - dAtA[i] = 0x18 - } - if len(m.CurrentStateRoot) > 0 { - i -= len(m.CurrentStateRoot) - copy(dAtA[i:], m.CurrentStateRoot) - i = encodeVarintQuery(dAtA, i, uint64(len(m.CurrentStateRoot))) - i-- - dAtA[i] = 0x12 - } - if len(m.NextValidatorSetHash) > 0 { - i -= len(m.NextValidatorSetHash) - copy(dAtA[i:], m.NextValidatorSetHash) - i = encodeVarintQuery(dAtA, i, uint64(len(m.NextValidatorSetHash))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -559,26 +450,6 @@ func (m *QueryVoteExtBodyByHeightRequest) Size() (n int) { return n } -func (m *QueryVoteExtBodyByHeightResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.NextValidatorSetHash) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.CurrentStateRoot) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.CurrentBlockHeight != 0 { - n += 1 + sovQuery(uint64(m.CurrentBlockHeight)) - } - return n -} - func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -787,143 +658,6 @@ func (m *QueryVoteExtBodyByHeightRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryVoteExtBodyByHeightResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: QueryVoteExtBodyByHeightResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryVoteExtBodyByHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorSetHash", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.NextValidatorSetHash = append(m.NextValidatorSetHash[:0], dAtA[iNdEx:postIndex]...) - if m.NextValidatorSetHash == nil { - m.NextValidatorSetHash = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CurrentStateRoot", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.CurrentStateRoot = append(m.CurrentStateRoot[:0], dAtA[iNdEx:postIndex]...) - if m.CurrentStateRoot == nil { - m.CurrentStateRoot = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CurrentBlockHeight", wireType) - } - m.CurrentBlockHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.CurrentBlockHeight |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/votepersistence/types/vote_ext_body.pb.go b/x/votepersistence/types/vote_ext_body.pb.go new file mode 100644 index 00000000..918fd218 --- /dev/null +++ b/x/votepersistence/types/vote_ext_body.pb.go @@ -0,0 +1,467 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/votepersistence/v1/vote_ext_body.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// VoteExtBody defines the VoteExtBody message. +type VoteExtBody struct { + NextValidatorSetHash []byte `protobuf:"bytes,1,opt,name=next_validator_set_hash,json=nextValidatorSetHash,proto3" json:"next_validator_set_hash,omitempty"` + CurrentStateRoot []byte `protobuf:"bytes,2,opt,name=current_state_root,json=currentStateRoot,proto3" json:"current_state_root,omitempty"` + CurrentBlockHeight int64 `protobuf:"varint,3,opt,name=current_block_height,json=currentBlockHeight,proto3" json:"current_block_height,omitempty"` + ActionsReducedRoot string `protobuf:"bytes,4,opt,name=actions_reduced_root,json=actionsReducedRoot,proto3" json:"actions_reduced_root,omitempty"` +} + +func (m *VoteExtBody) Reset() { *m = VoteExtBody{} } +func (m *VoteExtBody) String() string { return proto.CompactTextString(m) } +func (*VoteExtBody) ProtoMessage() {} +func (*VoteExtBody) Descriptor() ([]byte, []int) { + return fileDescriptor_fc9a8a749a7bb705, []int{0} +} +func (m *VoteExtBody) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VoteExtBody) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VoteExtBody.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 *VoteExtBody) XXX_Merge(src proto.Message) { + xxx_messageInfo_VoteExtBody.Merge(m, src) +} +func (m *VoteExtBody) XXX_Size() int { + return m.Size() +} +func (m *VoteExtBody) XXX_DiscardUnknown() { + xxx_messageInfo_VoteExtBody.DiscardUnknown(m) +} + +var xxx_messageInfo_VoteExtBody proto.InternalMessageInfo + +func (m *VoteExtBody) GetNextValidatorSetHash() []byte { + if m != nil { + return m.NextValidatorSetHash + } + return nil +} + +func (m *VoteExtBody) GetCurrentStateRoot() []byte { + if m != nil { + return m.CurrentStateRoot + } + return nil +} + +func (m *VoteExtBody) GetCurrentBlockHeight() int64 { + if m != nil { + return m.CurrentBlockHeight + } + return 0 +} + +func (m *VoteExtBody) GetActionsReducedRoot() string { + if m != nil { + return m.ActionsReducedRoot + } + return "" +} + +func init() { + proto.RegisterType((*VoteExtBody)(nil), "pulsarchain.votepersistence.v1.VoteExtBody") +} + +func init() { + proto.RegisterFile("pulsarchain/votepersistence/v1/vote_ext_body.proto", fileDescriptor_fc9a8a749a7bb705) +} + +var fileDescriptor_fc9a8a749a7bb705 = []byte{ + // 298 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0xd0, 0x31, 0x4b, 0xc3, 0x40, + 0x14, 0x07, 0xf0, 0x9e, 0x15, 0xc1, 0xe8, 0x20, 0xa1, 0x60, 0xa7, 0xa3, 0x38, 0x75, 0xb0, 0x49, + 0xa3, 0xb8, 0x38, 0x16, 0x84, 0xce, 0xa9, 0x74, 0x70, 0x39, 0x2e, 0x97, 0x47, 0xef, 0xb0, 0xe6, + 0x85, 0xbb, 0x97, 0xd0, 0x7e, 0x0b, 0x3f, 0x96, 0x63, 0x27, 0x71, 0x94, 0xf6, 0x8b, 0xc8, 0x25, + 0x0d, 0x88, 0xae, 0xf7, 0xbb, 0xff, 0xfb, 0xc3, 0x3f, 0xb8, 0x2b, 0xab, 0xb5, 0x93, 0x56, 0x69, + 0x69, 0x8a, 0xb8, 0x46, 0x82, 0x12, 0xac, 0x33, 0x8e, 0xa0, 0x50, 0x10, 0xd7, 0x49, 0xf3, 0x24, + 0x60, 0x43, 0x22, 0xc3, 0x7c, 0x1b, 0x95, 0x16, 0x09, 0x43, 0xfe, 0x2b, 0x13, 0xfd, 0xc9, 0x44, + 0x75, 0x72, 0xf3, 0xc9, 0x82, 0x8b, 0x25, 0x12, 0x3c, 0x6d, 0x68, 0x86, 0xf9, 0x36, 0x7c, 0x08, + 0xae, 0x0b, 0x7f, 0xa2, 0x96, 0x6b, 0x93, 0x4b, 0x42, 0x2b, 0x1c, 0x90, 0xd0, 0xd2, 0xe9, 0x21, + 0x1b, 0xb1, 0xf1, 0x65, 0x3a, 0xf0, 0xbc, 0xec, 0x74, 0x01, 0x34, 0x97, 0x4e, 0x87, 0xb7, 0x41, + 0xa8, 0x2a, 0x6b, 0xa1, 0x20, 0xe1, 0x48, 0x12, 0x08, 0x8b, 0x48, 0xc3, 0x93, 0x26, 0x71, 0x75, + 0x94, 0x85, 0x87, 0x14, 0x91, 0xc2, 0x69, 0x30, 0xe8, 0x7e, 0x67, 0x6b, 0x54, 0xaf, 0x42, 0x83, + 0x59, 0x69, 0x1a, 0xf6, 0x47, 0x6c, 0xdc, 0x4f, 0xbb, 0x4b, 0x33, 0x4f, 0xf3, 0x46, 0x7c, 0x42, + 0x2a, 0x32, 0x58, 0x38, 0x61, 0x21, 0xaf, 0x14, 0xe4, 0x6d, 0xc3, 0xe9, 0x88, 0x8d, 0xcf, 0xd3, + 0xf0, 0x68, 0x69, 0x4b, 0xbe, 0x63, 0xf6, 0xfc, 0xb1, 0xe7, 0x6c, 0xb7, 0xe7, 0xec, 0x7b, 0xcf, + 0xd9, 0xfb, 0x81, 0xf7, 0x76, 0x07, 0xde, 0xfb, 0x3a, 0xf0, 0xde, 0xcb, 0xe3, 0xca, 0x90, 0xae, + 0xb2, 0x48, 0xe1, 0x5b, 0x5c, 0x60, 0x0e, 0xc9, 0x34, 0x99, 0x18, 0x8c, 0xdb, 0xa1, 0x26, 0xed, + 0xba, 0x9b, 0x7f, 0xfb, 0xd2, 0xb6, 0x04, 0x97, 0x9d, 0x35, 0xab, 0xde, 0xff, 0x04, 0x00, 0x00, + 0xff, 0xff, 0xbd, 0xc8, 0x3f, 0x5d, 0x8b, 0x01, 0x00, 0x00, +} + +func (m *VoteExtBody) 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 *VoteExtBody) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VoteExtBody) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ActionsReducedRoot) > 0 { + i -= len(m.ActionsReducedRoot) + copy(dAtA[i:], m.ActionsReducedRoot) + i = encodeVarintVoteExtBody(dAtA, i, uint64(len(m.ActionsReducedRoot))) + i-- + dAtA[i] = 0x22 + } + if m.CurrentBlockHeight != 0 { + i = encodeVarintVoteExtBody(dAtA, i, uint64(m.CurrentBlockHeight)) + i-- + dAtA[i] = 0x18 + } + if len(m.CurrentStateRoot) > 0 { + i -= len(m.CurrentStateRoot) + copy(dAtA[i:], m.CurrentStateRoot) + i = encodeVarintVoteExtBody(dAtA, i, uint64(len(m.CurrentStateRoot))) + i-- + dAtA[i] = 0x12 + } + if len(m.NextValidatorSetHash) > 0 { + i -= len(m.NextValidatorSetHash) + copy(dAtA[i:], m.NextValidatorSetHash) + i = encodeVarintVoteExtBody(dAtA, i, uint64(len(m.NextValidatorSetHash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintVoteExtBody(dAtA []byte, offset int, v uint64) int { + offset -= sovVoteExtBody(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *VoteExtBody) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NextValidatorSetHash) + if l > 0 { + n += 1 + l + sovVoteExtBody(uint64(l)) + } + l = len(m.CurrentStateRoot) + if l > 0 { + n += 1 + l + sovVoteExtBody(uint64(l)) + } + if m.CurrentBlockHeight != 0 { + n += 1 + sovVoteExtBody(uint64(m.CurrentBlockHeight)) + } + l = len(m.ActionsReducedRoot) + if l > 0 { + n += 1 + l + sovVoteExtBody(uint64(l)) + } + return n +} + +func sovVoteExtBody(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozVoteExtBody(x uint64) (n int) { + return sovVoteExtBody(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *VoteExtBody) 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 ErrIntOverflowVoteExtBody + } + 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: VoteExtBody: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VoteExtBody: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorSetHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVoteExtBody + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthVoteExtBody + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthVoteExtBody + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorSetHash = append(m.NextValidatorSetHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorSetHash == nil { + m.NextValidatorSetHash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentStateRoot", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVoteExtBody + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthVoteExtBody + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthVoteExtBody + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CurrentStateRoot = append(m.CurrentStateRoot[:0], dAtA[iNdEx:postIndex]...) + if m.CurrentStateRoot == nil { + m.CurrentStateRoot = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentBlockHeight", wireType) + } + m.CurrentBlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVoteExtBody + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CurrentBlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ActionsReducedRoot", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVoteExtBody + } + 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 ErrInvalidLengthVoteExtBody + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthVoteExtBody + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ActionsReducedRoot = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipVoteExtBody(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthVoteExtBody + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipVoteExtBody(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowVoteExtBody + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowVoteExtBody + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowVoteExtBody + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthVoteExtBody + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupVoteExtBody + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthVoteExtBody + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthVoteExtBody = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowVoteExtBody = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupVoteExtBody = fmt.Errorf("proto: unexpected end of group") +) From bf0e88e49b85370b1f273f9f64e6ed01164b8b21 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 19:22:48 +0300 Subject: [PATCH 34/63] fix: script was not refreshing based on code changes, fixed --- scripts/setup_local_testnet.sh | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/scripts/setup_local_testnet.sh b/scripts/setup_local_testnet.sh index 6873e6e3..6f62c5fa 100755 --- a/scripts/setup_local_testnet.sh +++ b/scripts/setup_local_testnet.sh @@ -7,7 +7,7 @@ REPO_ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd)" PYTHON_HELPER="$SCRIPT_DIR/setup_local_testnet_helper.py" GO_HELPER="$SCRIPT_DIR/derive_mina_pub.go" -CHAIN_HOME="${CHAIN_HOME:-$HOME/.pulsar-chain}" +CHAIN_HOME="${CHAIN_HOME:-$HOME/.pulsar}" CHAIN_ID="${CHAIN_ID:-mytestnet}" MONIKER="${MONIKER:-mynode}" KEY_NAME="${KEY_NAME:-alice}" @@ -18,14 +18,9 @@ BOND_AMOUNT="${BOND_AMOUNT:-100000000}" MIN_GAS_PRICE="${MIN_GAS_PRICE:-0.0001pmina}" VOTE_EXT_ENABLE_HEIGHT="${VOTE_EXT_ENABLE_HEIGHT:-1}" CONFIG_YML_PATH="${CONFIG_YML_PATH:-$REPO_ROOT/config.yml}" -TMP_BUILD_DIR="$(mktemp -d "${TMPDIR:-/tmp}/pulsar-localnet.XXXXXX")" -BINARY_PATH="$TMP_BUILD_DIR/pulsar-chaind" - -cleanup() { - rm -rf "$TMP_BUILD_DIR" -} - -trap cleanup EXIT +BIN_DIR="${BIN_DIR:-$HOME/go/bin}" +BINARY_PATH="${BINARY_PATH:-$BIN_DIR/pulsard}" +COMPAT_BINARY_PATH="${COMPAT_BINARY_PATH:-$BIN_DIR/pulsar-chaind}" require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then @@ -59,12 +54,17 @@ APP_FILE="$CHAIN_HOME/config/app.toml" echo "==> Cleaning previous homes..." rm -rf "$CHAIN_HOME" "$HOME/.pulsar-node1" "$HOME/.pulsar-node2" -echo "==> Building temporary binary..." +echo "==> Building binary..." +mkdir -p "$BIN_DIR" ( cd "$REPO_ROOT" go build -o "$BINARY_PATH" ./cmd/pulsard ) +if [[ "$COMPAT_BINARY_PATH" != "$BINARY_PATH" ]]; then + cp "$BINARY_PATH" "$COMPAT_BINARY_PATH" +fi + echo "==> Initializing chain home..." "$BINARY_PATH" init "$MONIKER" --chain-id "$CHAIN_ID" --home "$CHAIN_HOME" >/dev/null @@ -107,9 +107,15 @@ echo "==> Validating final genesis..." echo "" echo "Setup complete." echo " home: $CHAIN_HOME" +echo " binary: $BINARY_PATH" +echo " compat: $COMPAT_BINARY_PATH" echo " validator: $KEY_NAME" echo " cosmos_key: $COSMOS_PUB_KEY" echo " mina_key: $MINA_PUB_KEY" echo "" +echo "Query example:" +echo " $BINARY_PATH query votepersistence vote-ext-body-by-height 5 --home $CHAIN_HOME" +echo " $COMPAT_BINARY_PATH query votepersistence vote-ext-body-by-height 5 --home $CHAIN_HOME" +echo "" echo "==> Starting chain..." -"$BINARY_PATH" start --home "$CHAIN_HOME" +exec "$BINARY_PATH" start --home "$CHAIN_HOME" From cfd44a3d03dcdd8cb5c993657db8fe316daecf00 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 20:03:44 +0300 Subject: [PATCH 35/63] refactor: use proto in payload and update the logic accordingly --- abci/helpers.go | 56 +-- abci/pre_blocker.go | 6 +- abci/prepare_proposal.go | 4 +- abci/types.go | 5 - api/pulsarchain/abci/payload.pb.go | 590 +++++++++++++++++++++++++++ proto/pulsarchain/abci/payload.proto | 15 + x/votepersistence/types/query.pb.go | 7 +- 7 files changed, 641 insertions(+), 42 deletions(-) create mode 100644 api/pulsarchain/abci/payload.pb.go create mode 100644 proto/pulsarchain/abci/payload.proto diff --git a/abci/helpers.go b/abci/helpers.go index 2e1c47b2..e26373ff 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -4,11 +4,9 @@ import ( "bytes" "context" "encoding/hex" - "encoding/json" "fmt" "math/big" "sort" - "strings" abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -17,6 +15,7 @@ import ( "github.com/node101-io/mina-signer-go/field" "github.com/node101-io/mina-signer-go/keys" "github.com/node101-io/mina-signer-go/poseidon" + abcipb "github.com/node101-io/pulsar-chain/api/pulsarchain/abci" "github.com/node101-io/pulsar-chain/x/votepersistence/types" votepersistenceTypes "github.com/node101-io/pulsar-chain/x/votepersistence/types" ) @@ -29,34 +28,32 @@ func MockSignatureVerify(signature []byte, message votepersistenceTypes.VoteExtB return true } -func extractPayload(txs [][]byte) (Payload, error) { +func extractPayload(txs [][]byte) (abcipb.Payload, error) { if len(txs) == 0 { - return Payload{}, ErrEmptyBlock + return abcipb.Payload{}, ErrEmptyBlock } - voteExtensionTx := txs[0] - - if !strings.Contains(string(txs[0]), VoteExtMarker) { - return Payload{}, types.ErrVoteExtMarkerNotFound + if !bytes.HasPrefix(txs[0], []byte(VoteExtMarker)) { + return abcipb.Payload{}, types.ErrVoteExtMarkerNotFound } - voteExtensionTx = voteExtensionTx[len([]byte(VoteExtMarker)):] + voteExtensionTx := txs[0][len([]byte(VoteExtMarker)):] - var pl Payload + var pl abcipb.Payload - err := json.Unmarshal(voteExtensionTx, &pl) + err := pl.Unmarshal(voteExtensionTx) if err != nil { - return Payload{}, err + return abcipb.Payload{}, err } return pl, nil } -func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl Payload, body votepersistenceTypes.VoteExtBody) error { +func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl abcipb.Payload, body votepersistenceTypes.VoteExtBody) error { - for publicKey, vote := range pl.Votes { + for _, vote := range pl.Votes { - pk, err := hex.DecodeString(publicKey) + pk, err := hex.DecodeString(vote.ConsensusPublicKey) if err != nil { return err } @@ -74,7 +71,7 @@ func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl Payload, body return err } - if !MockSignatureVerify(vote, body, minaKey, ActionsReducedRoot) { + if !MockSignatureVerify(vote.VoteExtension, body, minaKey, ActionsReducedRoot) { return types.ErrInvalidVoteExtension.Wrap("invalid signature") } @@ -200,7 +197,7 @@ func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []staki } -func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl Payload) (bool, error) { +func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl abcipb.Payload) (bool, error) { var signedStakePower int64 var currentValidatorStakePower int64 @@ -228,8 +225,8 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl Pay currentValidatorStakePower += val.GetConsensusPower(sdk.DefaultPowerReduction) } - for addr := range pl.Votes { - validatorInfo, ok := valInfoMap[addr] + for _, vote := range pl.Votes { + validatorInfo, ok := valInfoMap[vote.ConsensusPublicKey] if ok { signedStakePower += validatorInfo.GetConsensusPower(sdk.DefaultPowerReduction) } @@ -285,13 +282,15 @@ func (h *AbciHandler) getValidatorPublicKey(ctx sdk.Context, validatorAddr []byt return cosmosValidatorPubKey.Bytes(), nil } -func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteExtensions []abci.ExtendedVoteInfo) (Payload, error) { - voteExtsForGivenBlock := make(map[string][]byte) +func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteExtensions []abci.ExtendedVoteInfo) (abcipb.Payload, error) { + + var voteExtsForGivenBlock []*abcipb.Votes + currentValidatorSetMap := make(map[string]bool) currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) if err != nil { - return Payload{}, err + return abcipb.Payload{}, err } for _, currentValidator := range currentValidatorSet { @@ -304,7 +303,7 @@ func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteE currentValidatorSetMap[string(consAddr)] = true } - for i, vote := range voteExtensions { + for _, vote := range voteExtensions { if !currentValidatorSetMap[string(vote.Validator.Address)] { continue @@ -312,15 +311,18 @@ func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteE cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, vote.Validator.Address) if err != nil { - return Payload{}, err + return abcipb.Payload{}, err } - voteExtsForGivenBlock[hex.EncodeToString(cosmosValidatorPubKey)] = voteExtensions[i].VoteExtension + voteExtsForGivenBlock = append(voteExtsForGivenBlock, &abcipb.Votes{ + ConsensusPublicKey: hex.EncodeToString(cosmosValidatorPubKey), + VoteExtension: vote.VoteExtension, + }) } if len(voteExtsForGivenBlock) == 0 { - return Payload{}, nil + return abcipb.Payload{}, nil } - return Payload{Height: blockHeight - 1, Votes: voteExtsForGivenBlock}, nil + return abcipb.Payload{Height: blockHeight - 1, Votes: voteExtsForGivenBlock}, nil } diff --git a/abci/pre_blocker.go b/abci/pre_blocker.go index aab27f7c..5677638b 100644 --- a/abci/pre_blocker.go +++ b/abci/pre_blocker.go @@ -48,9 +48,9 @@ func (h *AbciHandler) PreBlocker() sdk.PreBlocker { currentValidatorSetMap[hex.EncodeToString(cosmosValidatorPublicKey)] = cosmosValidatorPublicKey } - for addr, vote := range pl.Votes { + for _, vote := range pl.Votes { - cosmosValidatorPublicKey, ok := currentValidatorSetMap[addr] + cosmosValidatorPublicKey, ok := currentValidatorSetMap[vote.ConsensusPublicKey] if !ok { continue } @@ -69,7 +69,7 @@ func (h *AbciHandler) PreBlocker() sdk.PreBlocker { return nil, err } - err = h.votePersistenceKeeper.SetVote(ctx, req.GetHeight()-2, minaKey, vote) + err = h.votePersistenceKeeper.SetVote(ctx, req.GetHeight()-2, minaKey, vote.VoteExtension) if err != nil { return nil, err } diff --git a/abci/prepare_proposal.go b/abci/prepare_proposal.go index 5a6a83b8..0cde5942 100644 --- a/abci/prepare_proposal.go +++ b/abci/prepare_proposal.go @@ -1,8 +1,6 @@ package vote_ext import ( - "encoding/json" - abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -23,7 +21,7 @@ func (h *AbciHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return &abci.ResponsePrepareProposal{Txs: req.Txs}, err } - bz, err := json.Marshal(pl) + bz, err := pl.Marshal() if err != nil { return nil, err } diff --git a/abci/types.go b/abci/types.go index 1a76b191..43ce10ce 100644 --- a/abci/types.go +++ b/abci/types.go @@ -7,8 +7,3 @@ const ActionsReducedRoot string = "pulsar" var VoteExtMarker string = "VOTEEXT:" var ErrEmptyBlock error = errors.New("this block has no transaction") - -type Payload struct { - Height int64 `json:"height"` - Votes map[string][]byte `json:"votes"` -} diff --git a/api/pulsarchain/abci/payload.pb.go b/api/pulsarchain/abci/payload.pb.go new file mode 100644 index 00000000..6adc1b07 --- /dev/null +++ b/api/pulsarchain/abci/payload.pb.go @@ -0,0 +1,590 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/abci/payload.proto + +package abcipb + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type Payload struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Votes []*Votes `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes,omitempty"` +} + +func (m *Payload) Reset() { *m = Payload{} } +func (m *Payload) String() string { return proto.CompactTextString(m) } +func (*Payload) ProtoMessage() {} +func (*Payload) Descriptor() ([]byte, []int) { + return fileDescriptor_5a138d1c833ef562, []int{0} +} +func (m *Payload) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Payload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Payload.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 *Payload) XXX_Merge(src proto.Message) { + xxx_messageInfo_Payload.Merge(m, src) +} +func (m *Payload) XXX_Size() int { + return m.Size() +} +func (m *Payload) XXX_DiscardUnknown() { + xxx_messageInfo_Payload.DiscardUnknown(m) +} + +var xxx_messageInfo_Payload proto.InternalMessageInfo + +func (m *Payload) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Payload) GetVotes() []*Votes { + if m != nil { + return m.Votes + } + return nil +} + +type Votes struct { + ConsensusPublicKey string `protobuf:"bytes,1,opt,name=consensus_public_key,json=consensusPublicKey,proto3" json:"consensus_public_key,omitempty"` + VoteExtension []byte `protobuf:"bytes,2,opt,name=vote_extension,json=voteExtension,proto3" json:"vote_extension,omitempty"` +} + +func (m *Votes) Reset() { *m = Votes{} } +func (m *Votes) String() string { return proto.CompactTextString(m) } +func (*Votes) ProtoMessage() {} +func (*Votes) Descriptor() ([]byte, []int) { + return fileDescriptor_5a138d1c833ef562, []int{1} +} +func (m *Votes) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Votes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Votes.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 *Votes) XXX_Merge(src proto.Message) { + xxx_messageInfo_Votes.Merge(m, src) +} +func (m *Votes) XXX_Size() int { + return m.Size() +} +func (m *Votes) XXX_DiscardUnknown() { + xxx_messageInfo_Votes.DiscardUnknown(m) +} + +var xxx_messageInfo_Votes proto.InternalMessageInfo + +func (m *Votes) GetConsensusPublicKey() string { + if m != nil { + return m.ConsensusPublicKey + } + return "" +} + +func (m *Votes) GetVoteExtension() []byte { + if m != nil { + return m.VoteExtension + } + return nil +} + +func init() { + proto.RegisterType((*Payload)(nil), "pulsarchain.abci.Payload") + proto.RegisterType((*Votes)(nil), "pulsarchain.abci.Votes") +} + +func init() { proto.RegisterFile("pulsarchain/abci/payload.proto", fileDescriptor_5a138d1c833ef562) } + +var fileDescriptor_5a138d1c833ef562 = []byte{ + // 260 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x4f, 0x4c, 0x4a, 0xce, 0xd4, 0x2f, 0x48, 0xac, + 0xcc, 0xc9, 0x4f, 0x4c, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x40, 0x92, 0xd7, 0x03, + 0xc9, 0x2b, 0x05, 0x70, 0xb1, 0x07, 0x40, 0x94, 0x08, 0x89, 0x71, 0xb1, 0x65, 0xa4, 0x66, 0xa6, + 0x67, 0x94, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0x41, 0x79, 0x42, 0xba, 0x5c, 0xac, 0x65, + 0xf9, 0x25, 0xa9, 0xc5, 0x12, 0x4c, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, 0xe2, 0x7a, 0xe8, 0x86, 0xe8, + 0x85, 0x81, 0xa4, 0x83, 0x20, 0xaa, 0x94, 0x12, 0xb8, 0x58, 0xc1, 0x7c, 0x21, 0x03, 0x2e, 0x91, + 0xe4, 0xfc, 0xbc, 0xe2, 0xd4, 0xbc, 0xe2, 0xd2, 0xe2, 0xf8, 0x82, 0xd2, 0xa4, 0x9c, 0xcc, 0xe4, + 0xf8, 0xec, 0xd4, 0x4a, 0xb0, 0xe9, 0x9c, 0x41, 0x42, 0x70, 0xb9, 0x00, 0xb0, 0x94, 0x77, 0x6a, + 0xa5, 0x90, 0x2a, 0x17, 0x1f, 0xc8, 0x8c, 0xf8, 0xd4, 0x8a, 0x92, 0xd4, 0xbc, 0xe2, 0xcc, 0xfc, + 0x3c, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x9e, 0x20, 0x5e, 0x90, 0xa8, 0x2b, 0x4c, 0xd0, 0x29, 0xe2, + 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, + 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xec, 0xd2, 0x33, 0x4b, 0x32, 0x4a, + 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xf3, 0xf2, 0x53, 0x52, 0x0d, 0x0d, 0x0c, 0x75, 0x33, 0xf3, + 0xf5, 0x21, 0x0e, 0xd6, 0x85, 0x06, 0x4b, 0x41, 0xa6, 0x3e, 0x7a, 0x30, 0x59, 0x83, 0x88, 0x82, + 0xa4, 0x24, 0x36, 0x70, 0x30, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x85, 0xf8, 0xb6, 0x21, + 0x48, 0x01, 0x00, 0x00, +} + +func (m *Payload) 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 *Payload) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Payload) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPayload(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Height != 0 { + i = encodeVarintPayload(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Votes) 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 *Votes) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Votes) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.VoteExtension) > 0 { + i -= len(m.VoteExtension) + copy(dAtA[i:], m.VoteExtension) + i = encodeVarintPayload(dAtA, i, uint64(len(m.VoteExtension))) + i-- + dAtA[i] = 0x12 + } + if len(m.ConsensusPublicKey) > 0 { + i -= len(m.ConsensusPublicKey) + copy(dAtA[i:], m.ConsensusPublicKey) + i = encodeVarintPayload(dAtA, i, uint64(len(m.ConsensusPublicKey))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintPayload(dAtA []byte, offset int, v uint64) int { + offset -= sovPayload(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Payload) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovPayload(uint64(m.Height)) + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovPayload(uint64(l)) + } + } + return n +} + +func (m *Votes) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ConsensusPublicKey) + if l > 0 { + n += 1 + l + sovPayload(uint64(l)) + } + l = len(m.VoteExtension) + if l > 0 { + n += 1 + l + sovPayload(uint64(l)) + } + return n +} + +func sovPayload(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozPayload(x uint64) (n int) { + return sovPayload(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Payload) 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 ErrIntOverflowPayload + } + 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: Payload: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Payload: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPayload + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPayload + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPayload + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPayload + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, &Votes{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPayload(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPayload + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Votes) 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 ErrIntOverflowPayload + } + 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: Votes: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Votes: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusPublicKey", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPayload + } + 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 ErrInvalidLengthPayload + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPayload + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConsensusPublicKey = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteExtension", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPayload + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthPayload + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthPayload + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VoteExtension = append(m.VoteExtension[:0], dAtA[iNdEx:postIndex]...) + if m.VoteExtension == nil { + m.VoteExtension = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPayload(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPayload + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipPayload(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPayload + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPayload + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPayload + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthPayload + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupPayload + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthPayload + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthPayload = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowPayload = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupPayload = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/pulsarchain/abci/payload.proto b/proto/pulsarchain/abci/payload.proto new file mode 100644 index 00000000..e3982816 --- /dev/null +++ b/proto/pulsarchain/abci/payload.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package pulsarchain.abci; + +option go_package = "github.com/node101-io/pulsar-chain/api/pulsarchain/abci;abcipb"; + +message Payload { + int64 height = 1; + repeated Votes votes = 2; +} + +message Votes { + string consensus_public_key = 1; + bytes vote_extension = 2; +} diff --git a/x/votepersistence/types/query.pb.go b/x/votepersistence/types/query.pb.go index 4fa36cb2..8c9a2ecf 100644 --- a/x/votepersistence/types/query.pb.go +++ b/x/votepersistence/types/query.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. From ab1ce6785e129211b3a8112a6463a82231326840 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 20:19:01 +0300 Subject: [PATCH 36/63] fix: the script now initializes chain with 2 validators, allowing to test verify vote extension --- scripts/setup_local_testnet.sh | 183 ++++++++++++++++++-------- scripts/setup_local_testnet_helper.py | 56 ++++++-- 2 files changed, 178 insertions(+), 61 deletions(-) diff --git a/scripts/setup_local_testnet.sh b/scripts/setup_local_testnet.sh index 6f62c5fa..fc46e10d 100755 --- a/scripts/setup_local_testnet.sh +++ b/scripts/setup_local_testnet.sh @@ -7,17 +7,30 @@ REPO_ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd)" PYTHON_HELPER="$SCRIPT_DIR/setup_local_testnet_helper.py" GO_HELPER="$SCRIPT_DIR/derive_mina_pub.go" -CHAIN_HOME="${CHAIN_HOME:-$HOME/.pulsar}" +LEGACY_CHAIN_HOME="${CHAIN_HOME:-$HOME/.pulsar}" +NODE1_HOME="${NODE1_HOME:-$HOME/.pulsar-node1}" +NODE2_HOME="${NODE2_HOME:-$HOME/.pulsar-node2}" CHAIN_ID="${CHAIN_ID:-mytestnet}" -MONIKER="${MONIKER:-mynode}" -KEY_NAME="${KEY_NAME:-alice}" +NODE1_MONIKER="${NODE1_MONIKER:-node1}" +NODE2_MONIKER="${NODE2_MONIKER:-node2}" +NODE1_KEY_NAME="${NODE1_KEY_NAME:-validator1}" +NODE2_KEY_NAME="${NODE2_KEY_NAME:-validator2}" KEYRING_BACKEND="${KEYRING_BACKEND:-test}" DENOM="${DENOM:-pmina}" -GENESIS_BALANCE="${GENESIS_BALANCE:-1000000000}" +STAKE_AMOUNT="${STAKE_AMOUNT:-1000000000}" BOND_AMOUNT="${BOND_AMOUNT:-100000000}" MIN_GAS_PRICE="${MIN_GAS_PRICE:-0.0001pmina}" -VOTE_EXT_ENABLE_HEIGHT="${VOTE_EXT_ENABLE_HEIGHT:-1}" -CONFIG_YML_PATH="${CONFIG_YML_PATH:-$REPO_ROOT/config.yml}" +VOTE_EXT_ENABLE_HEIGHT="${VOTE_EXT_ENABLE_HEIGHT:-2}" +NODE1_MINA_PRIV_KEY="${NODE1_MINA_PRIV_KEY:-ES17xFroE2/QOa9yCLXsQ9sJMeIUVwr2ZXcdWGjNLlM=}" +NODE2_MINA_PRIV_KEY="${NODE2_MINA_PRIV_KEY:-PKeRXivUb4gZ/nMKxUK5beEnVJwIrzN71mAf7JVKsng=}" +NODE1_P2P_PORT="${NODE1_P2P_PORT:-26656}" +NODE1_RPC_PORT="${NODE1_RPC_PORT:-26657}" +NODE2_P2P_PORT="${NODE2_P2P_PORT:-26666}" +NODE2_RPC_PORT="${NODE2_RPC_PORT:-26667}" +NODE1_GRPC_PORT="${NODE1_GRPC_PORT:-9090}" +NODE2_GRPC_PORT="${NODE2_GRPC_PORT:-9091}" +NODE1_API_PORT="${NODE1_API_PORT:-1317}" +NODE2_API_PORT="${NODE2_API_PORT:-1318}" BIN_DIR="${BIN_DIR:-$HOME/go/bin}" BINARY_PATH="${BINARY_PATH:-$BIN_DIR/pulsard}" COMPAT_BINARY_PATH="${COMPAT_BINARY_PATH:-$BIN_DIR/pulsar-chaind}" @@ -29,30 +42,49 @@ require_cmd() { fi } -get_mina_priv_key() { - if [[ -n "${MINA_PRIV_KEY:-}" ]]; then - printf '%s\n' "$MINA_PRIV_KEY" - return - fi +derive_mina_pub_key() { + go run "$GO_HELPER" "$1" +} - python3 "$PYTHON_HELPER" read-mina-priv-key --config "$CONFIG_YML_PATH" +read_consensus_pub_key() { + python3 "$PYTHON_HELPER" read-consensus-pub-key --priv-validator-key "$1" } -derive_mina_pub_key() { - go run "$GO_HELPER" "$1" +configure_node() { + local home="$1" + local rpc_port="$2" + local p2p_port="$3" + local api_port="$4" + local grpc_port="$5" + local persistent_peers="$6" + local mina_priv_key="$7" + + sed -i.bak "s|laddr = \"tcp://127.0.0.1:26657\"|laddr = \"tcp://0.0.0.0:${rpc_port}\"|" "$home/config/config.toml" + sed -i.bak "s|laddr = \"tcp://0.0.0.0:26656\"|laddr = \"tcp://0.0.0.0:${p2p_port}\"|" "$home/config/config.toml" + sed -i.bak "s|persistent_peers = \"\"|persistent_peers = \"${persistent_peers}\"|" "$home/config/config.toml" + sed -i.bak 's|addr_book_strict = true|addr_book_strict = false|' "$home/config/config.toml" + sed -i.bak 's|allow_duplicate_ip = false|allow_duplicate_ip = true|' "$home/config/config.toml" + + sed -i.bak "s|address = \"tcp://localhost:1317\"|address = \"tcp://localhost:${api_port}\"|" "$home/config/app.toml" + sed -i.bak "s|address = \"localhost:9090\"|address = \"localhost:${grpc_port}\"|" "$home/config/app.toml" + + python3 "$PYTHON_HELPER" update-app-config \ + --app "$home/config/app.toml" \ + --min-gas-price "$MIN_GAS_PRICE" \ + --mina-priv-key "$mina_priv_key" } require_cmd go require_cmd python3 -MINA_PRIV_KEY="$(get_mina_priv_key)" -MINA_PUB_KEY="$(derive_mina_pub_key "$MINA_PRIV_KEY")" +NODE1_MINA_PUB_KEY="$(derive_mina_pub_key "$NODE1_MINA_PRIV_KEY")" +NODE2_MINA_PUB_KEY="$(derive_mina_pub_key "$NODE2_MINA_PRIV_KEY")" -GENESIS_FILE="$CHAIN_HOME/config/genesis.json" -APP_FILE="$CHAIN_HOME/config/app.toml" +NODE1_GENESIS_FILE="$NODE1_HOME/config/genesis.json" +NODE2_GENESIS_FILE="$NODE2_HOME/config/genesis.json" echo "==> Cleaning previous homes..." -rm -rf "$CHAIN_HOME" "$HOME/.pulsar-node1" "$HOME/.pulsar-node2" +rm -rf "$LEGACY_CHAIN_HOME" "$NODE1_HOME" "$NODE2_HOME" echo "==> Building binary..." mkdir -p "$BIN_DIR" @@ -65,57 +97,102 @@ if [[ "$COMPAT_BINARY_PATH" != "$BINARY_PATH" ]]; then cp "$BINARY_PATH" "$COMPAT_BINARY_PATH" fi -echo "==> Initializing chain home..." -"$BINARY_PATH" init "$MONIKER" --chain-id "$CHAIN_ID" --home "$CHAIN_HOME" >/dev/null +echo "==> Initializing nodes..." +"$BINARY_PATH" init "$NODE1_MONIKER" --chain-id "$CHAIN_ID" --home "$NODE1_HOME" >/dev/null 2>&1 +"$BINARY_PATH" init "$NODE2_MONIKER" --chain-id "$CHAIN_ID" --home "$NODE2_HOME" >/dev/null 2>&1 echo "==> Setting vote extension enable height..." python3 "$PYTHON_HELPER" set-vote-extension-height \ - --genesis "$GENESIS_FILE" \ + --genesis "$NODE1_GENESIS_FILE" \ --height "$VOTE_EXT_ENABLE_HEIGHT" -echo "==> Creating validator key..." -"$BINARY_PATH" keys add "$KEY_NAME" --home "$CHAIN_HOME" --keyring-backend "$KEYRING_BACKEND" >/dev/null +echo "==> Creating validator keys..." +"$BINARY_PATH" keys add "$NODE1_KEY_NAME" --home "$NODE1_HOME" --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 +"$BINARY_PATH" keys add "$NODE2_KEY_NAME" --home "$NODE2_HOME" --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 + +NODE1_ADDR="$("$BINARY_PATH" keys show "$NODE1_KEY_NAME" --address --home "$NODE1_HOME" --keyring-backend "$KEYRING_BACKEND")" +NODE2_ADDR="$("$BINARY_PATH" keys show "$NODE2_KEY_NAME" --address --home "$NODE2_HOME" --keyring-backend "$KEYRING_BACKEND")" -VALIDATOR_ADDR="$("$BINARY_PATH" keys show "$KEY_NAME" --address --home "$CHAIN_HOME" --keyring-backend "$KEYRING_BACKEND")" +echo "==> Adding genesis accounts..." +"$BINARY_PATH" genesis add-genesis-account "$NODE1_ADDR" "${STAKE_AMOUNT}${DENOM}" --home "$NODE1_HOME" >/dev/null 2>&1 +"$BINARY_PATH" genesis add-genesis-account "$NODE2_ADDR" "${STAKE_AMOUNT}${DENOM}" --home "$NODE1_HOME" >/dev/null 2>&1 + +echo "==> Creating gentx for ${NODE1_KEY_NAME}..." +"$BINARY_PATH" genesis gentx "$NODE1_KEY_NAME" "${BOND_AMOUNT}${DENOM}" \ + --chain-id "$CHAIN_ID" \ + --home "$NODE1_HOME" \ + --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 -echo "==> Adding genesis account for $KEY_NAME..." -"$BINARY_PATH" genesis add-genesis-account "$VALIDATOR_ADDR" "${GENESIS_BALANCE}${DENOM}" --home "$CHAIN_HOME" >/dev/null +echo "==> Copying shared genesis to node2..." +cp "$NODE1_GENESIS_FILE" "$NODE2_GENESIS_FILE" -echo "==> Creating gentx..." -"$BINARY_PATH" genesis gentx "$KEY_NAME" "${BOND_AMOUNT}${DENOM}" \ +echo "==> Creating gentx for ${NODE2_KEY_NAME}..." +"$BINARY_PATH" genesis gentx "$NODE2_KEY_NAME" "${BOND_AMOUNT}${DENOM}" \ --chain-id "$CHAIN_ID" \ - --home "$CHAIN_HOME" \ - --keyring-backend "$KEYRING_BACKEND" >/dev/null + --home "$NODE2_HOME" \ + --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 echo "==> Collecting gentxs..." -"$BINARY_PATH" genesis collect-gentxs --home "$CHAIN_HOME" >/dev/null +cp "$NODE2_HOME"/config/gentx/*.json "$NODE1_HOME/config/gentx/" +"$BINARY_PATH" genesis collect-gentxs --home "$NODE1_HOME" >/dev/null 2>&1 -echo "==> Patching keyregistry validator key pair from genesis validator pubkey..." -COSMOS_PUB_KEY="$(python3 "$PYTHON_HELPER" patch-keyregistry \ - --genesis "$GENESIS_FILE" \ - --mina-pub-key "$MINA_PUB_KEY")" +NODE1_COSMOS_PUB_KEY="$(read_consensus_pub_key "$NODE1_HOME/config/priv_validator_key.json")" +NODE2_COSMOS_PUB_KEY="$(read_consensus_pub_key "$NODE2_HOME/config/priv_validator_key.json")" -echo "==> Writing vote extension private key to app.toml..." -python3 "$PYTHON_HELPER" update-app-config \ - --app "$APP_FILE" \ - --min-gas-price "$MIN_GAS_PRICE" \ - --mina-priv-key "$MINA_PRIV_KEY" +echo "==> Patching keyregistry validator key pairs..." +python3 "$PYTHON_HELPER" patch-keyregistry \ + --genesis "$NODE1_GENESIS_FILE" \ + --cosmos-key "$NODE1_COSMOS_PUB_KEY" \ + --mina-pub-key "$NODE1_MINA_PUB_KEY" \ + --cosmos-key "$NODE2_COSMOS_PUB_KEY" \ + --mina-pub-key "$NODE2_MINA_PUB_KEY" >/dev/null echo "==> Validating final genesis..." -"$BINARY_PATH" genesis validate-genesis --home "$CHAIN_HOME" >/dev/null +"$BINARY_PATH" genesis validate-genesis --home "$NODE1_HOME" >/dev/null 2>&1 + +echo "==> Copying final genesis to node2..." +cp "$NODE1_GENESIS_FILE" "$NODE2_GENESIS_FILE" + +NODE1_ID="$("$BINARY_PATH" tendermint show-node-id --home "$NODE1_HOME")" +NODE2_ID="$("$BINARY_PATH" tendermint show-node-id --home "$NODE2_HOME")" + +echo "==> Configuring node1..." +configure_node \ + "$NODE1_HOME" \ + "$NODE1_RPC_PORT" \ + "$NODE1_P2P_PORT" \ + "$NODE1_API_PORT" \ + "$NODE1_GRPC_PORT" \ + "$NODE2_ID@127.0.0.1:$NODE2_P2P_PORT" \ + "$NODE1_MINA_PRIV_KEY" + +echo "==> Configuring node2..." +configure_node \ + "$NODE2_HOME" \ + "$NODE2_RPC_PORT" \ + "$NODE2_P2P_PORT" \ + "$NODE2_API_PORT" \ + "$NODE2_GRPC_PORT" \ + "$NODE1_ID@127.0.0.1:$NODE1_P2P_PORT" \ + "$NODE2_MINA_PRIV_KEY" echo "" echo "Setup complete." -echo " home: $CHAIN_HOME" -echo " binary: $BINARY_PATH" -echo " compat: $COMPAT_BINARY_PATH" -echo " validator: $KEY_NAME" -echo " cosmos_key: $COSMOS_PUB_KEY" -echo " mina_key: $MINA_PUB_KEY" +echo " binary: $BINARY_PATH" +echo " compat binary: $COMPAT_BINARY_PATH" +echo " node1 home: $NODE1_HOME" +echo " node2 home: $NODE2_HOME" +echo " node1 address: $NODE1_ADDR" +echo " node2 address: $NODE2_ADDR" +echo " node1 cosmos key: $NODE1_COSMOS_PUB_KEY" +echo " node2 cosmos key: $NODE2_COSMOS_PUB_KEY" +echo " node1 mina key: $NODE1_MINA_PUB_KEY" +echo " node2 mina key: $NODE2_MINA_PUB_KEY" echo "" -echo "Query example:" -echo " $BINARY_PATH query votepersistence vote-ext-body-by-height 5 --home $CHAIN_HOME" -echo " $COMPAT_BINARY_PATH query votepersistence vote-ext-body-by-height 5 --home $CHAIN_HOME" +echo "Start the nodes in separate terminals:" +echo " $BINARY_PATH start --home $NODE1_HOME" +echo " $BINARY_PATH start --home $NODE2_HOME" echo "" -echo "==> Starting chain..." -exec "$BINARY_PATH" start --home "$CHAIN_HOME" +echo "Validation examples:" +echo " curl -s http://localhost:$NODE1_RPC_PORT/validators | python3 -m json.tool | grep total" +echo " $BINARY_PATH query votepersistence vote-ext-body-by-height 5 --home $NODE1_HOME" diff --git a/scripts/setup_local_testnet_helper.py b/scripts/setup_local_testnet_helper.py index b86818fc..a84917d1 100644 --- a/scripts/setup_local_testnet_helper.py +++ b/scripts/setup_local_testnet_helper.py @@ -5,6 +5,7 @@ import re import sys from pathlib import Path +from typing import Optional def read_text(path_str: str) -> str: @@ -42,25 +43,58 @@ def set_vote_extension_height(genesis_path: str, height: str) -> int: return 0 -def patch_keyregistry(genesis_path: str, mina_pub_key: str) -> int: +def read_consensus_pub_key(priv_validator_key_path: str) -> int: + priv_validator_key = read_json(priv_validator_key_path) + print(priv_validator_key["pub_key"]["value"]) + return 0 + + +def extract_gentx_consensus_pub_keys(genesis) -> list[str]: + gentxs = genesis["app_state"]["genutil"]["gen_txs"] + cosmos_keys = [] + + for gentx in gentxs: + messages = gentx.get("body", {}).get("messages", []) + if not messages: + continue + + pub_key = messages[0].get("pubkey", {}).get("key") + if pub_key: + cosmos_keys.append(pub_key) + + return cosmos_keys + + +def patch_keyregistry( + genesis_path: str, mina_pub_keys: list[str], cosmos_keys: Optional[list[str]] = None +) -> int: genesis = read_json(genesis_path) - cosmos_pub_key = ( - genesis["app_state"]["genutil"]["gen_txs"][0]["body"]["messages"][0]["pubkey"]["key"] - ) + if not mina_pub_keys: + raise SystemExit("at least one --mina-pub-key is required") + + if cosmos_keys is None: + cosmos_keys = extract_gentx_consensus_pub_keys(genesis) + + if len(cosmos_keys) != len(mina_pub_keys): + raise SystemExit( + "validator key pair count mismatch: " + f"{len(cosmos_keys)} cosmos keys for {len(mina_pub_keys)} mina keys" + ) keyregistry = genesis["app_state"].setdefault("keyregistry", {}) keyregistry["params"] = keyregistry.get("params", {}) keyregistry["user_key_pairs"] = [] keyregistry["validator_key_pairs"] = [ { - "cosmos_key": cosmos_pub_key, + "cosmos_key": cosmos_key, "mina_key": mina_pub_key, } + for cosmos_key, mina_pub_key in zip(cosmos_keys, mina_pub_keys) ] write_json(genesis_path, genesis) - print(cosmos_pub_key) + print("\n".join(cosmos_keys)) return 0 @@ -95,13 +129,17 @@ def build_parser() -> argparse.ArgumentParser: read_key = subparsers.add_parser("read-mina-priv-key") read_key.add_argument("--config", required=True) + read_consensus_key = subparsers.add_parser("read-consensus-pub-key") + read_consensus_key.add_argument("--priv-validator-key", required=True) + set_height = subparsers.add_parser("set-vote-extension-height") set_height.add_argument("--genesis", required=True) set_height.add_argument("--height", required=True) patch_registry = subparsers.add_parser("patch-keyregistry") patch_registry.add_argument("--genesis", required=True) - patch_registry.add_argument("--mina-pub-key", required=True) + patch_registry.add_argument("--cosmos-key", action="append") + patch_registry.add_argument("--mina-pub-key", action="append", required=True) update_app = subparsers.add_parser("update-app-config") update_app.add_argument("--app", required=True) @@ -117,10 +155,12 @@ def main() -> int: if args.command == "read-mina-priv-key": return read_mina_priv_key(args.config) + if args.command == "read-consensus-pub-key": + return read_consensus_pub_key(args.priv_validator_key) if args.command == "set-vote-extension-height": return set_vote_extension_height(args.genesis, args.height) if args.command == "patch-keyregistry": - return patch_keyregistry(args.genesis, args.mina_pub_key) + return patch_keyregistry(args.genesis, args.mina_pub_key, args.cosmos_key) if args.command == "update-app-config": return update_app_config(args.app, args.min_gas_price, args.mina_priv_key) From ab2766d5ca54d743b63d66ac962547c51bfbb193 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 21:24:14 +0300 Subject: [PATCH 37/63] feat: implement signing/verifying vote extension bodies, using mina-signer-go --- abci/extend_vote.go | 2 +- abci/helpers.go | 49 ++++++++++++++++++++++++++++++++++++----- abci/verify_vote_ext.go | 2 +- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/abci/extend_vote.go b/abci/extend_vote.go index 776d3a6d..b2a5e25d 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -17,7 +17,7 @@ func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return nil, err } - bz := MockSign(body) + bz := h.secondaryKey.SignVoteExtBody(body) return &abci.ResponseExtendVote{VoteExtension: bz}, nil } diff --git a/abci/helpers.go b/abci/helpers.go index e26373ff..fbb15009 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -15,17 +15,56 @@ import ( "github.com/node101-io/mina-signer-go/field" "github.com/node101-io/mina-signer-go/keys" "github.com/node101-io/mina-signer-go/poseidon" + minasignature "github.com/node101-io/mina-signer-go/signature" abcipb "github.com/node101-io/pulsar-chain/api/pulsarchain/abci" "github.com/node101-io/pulsar-chain/x/votepersistence/types" votepersistenceTypes "github.com/node101-io/pulsar-chain/x/votepersistence/types" ) -func MockSign(voteExtBody votepersistenceTypes.VoteExtBody) []byte { - return []byte{} +func (s *SecondaryKey) SignVoteExtBody(voteExtBody votepersistenceTypes.VoteExtBody) []byte { + if s == nil || s.SecretKey == nil { + return nil + } + + msg, err := voteExtBody.Marshal() + if err != nil { + return nil + } + + sig, err := s.SecretKey.SignMessage(hex.EncodeToString(msg), "testnet") + if err != nil { + return nil + } + + bz, err := sig.MarshalBytes() + if err != nil { + return nil + } + + return bz } -func MockSignatureVerify(signature []byte, message votepersistenceTypes.VoteExtBody, minaKey []byte, reducedRoot string) bool { - return true +func VerifyVoteExtSig(signature []byte, message votepersistenceTypes.VoteExtBody, minaKey []byte, reducedRoot string) bool { + if message.ActionsReducedRoot != reducedRoot { + return false + } + + var pubKey keys.PublicKey + if err := pubKey.Unmarshal(minaKey); err != nil { + return false + } + + var sig minasignature.Signature + if err := sig.UnmarshalBytes(signature); err != nil { + return false + } + + msg, err := message.Marshal() + if err != nil { + return false + } + + return pubKey.VerifyMessage(&sig, hex.EncodeToString(msg), "testnet") } func extractPayload(txs [][]byte) (abcipb.Payload, error) { @@ -71,7 +110,7 @@ func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl abcipb.Payload return err } - if !MockSignatureVerify(vote.VoteExtension, body, minaKey, ActionsReducedRoot) { + if !VerifyVoteExtSig(vote.VoteExtension, body, minaKey, ActionsReducedRoot) { return types.ErrInvalidVoteExtension.Wrap("invalid signature") } diff --git a/abci/verify_vote_ext.go b/abci/verify_vote_ext.go index 167f3334..82cf9430 100644 --- a/abci/verify_vote_ext.go +++ b/abci/verify_vote_ext.go @@ -41,7 +41,7 @@ func (h *AbciHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandle return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err } - sigValidity := MockSignatureVerify(req.VoteExtension, body, minaKey, ActionsReducedRoot) + sigValidity := VerifyVoteExtSig(req.VoteExtension, body, minaKey, ActionsReducedRoot) if !sigValidity { return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err } From 961245e1a2d7f7755e5e6089ead491961da5a2cd Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 21:27:34 +0300 Subject: [PATCH 38/63] fix: start vote extension at height 3 --- scripts/setup_local_testnet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setup_local_testnet.sh b/scripts/setup_local_testnet.sh index fc46e10d..c31094d9 100755 --- a/scripts/setup_local_testnet.sh +++ b/scripts/setup_local_testnet.sh @@ -20,7 +20,7 @@ DENOM="${DENOM:-pmina}" STAKE_AMOUNT="${STAKE_AMOUNT:-1000000000}" BOND_AMOUNT="${BOND_AMOUNT:-100000000}" MIN_GAS_PRICE="${MIN_GAS_PRICE:-0.0001pmina}" -VOTE_EXT_ENABLE_HEIGHT="${VOTE_EXT_ENABLE_HEIGHT:-2}" +VOTE_EXT_ENABLE_HEIGHT="${VOTE_EXT_ENABLE_HEIGHT:-3}" NODE1_MINA_PRIV_KEY="${NODE1_MINA_PRIV_KEY:-ES17xFroE2/QOa9yCLXsQ9sJMeIUVwr2ZXcdWGjNLlM=}" NODE2_MINA_PRIV_KEY="${NODE2_MINA_PRIV_KEY:-PKeRXivUb4gZ/nMKxUK5beEnVJwIrzN71mAf7JVKsng=}" NODE1_P2P_PORT="${NODE1_P2P_PORT:-26656}" From f85b458bbe3c8e36134d6840e929da6f61acbfe7 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 1 May 2026 21:28:21 +0300 Subject: [PATCH 39/63] chore: remove empty block error and let prepare/process proposals start at height 4 --- abci/helpers.go | 2 +- abci/pre_blocker.go | 2 +- abci/prepare_proposal.go | 4 ++-- abci/process_proposal.go | 4 ++-- abci/types.go | 4 ---- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/abci/helpers.go b/abci/helpers.go index fbb15009..1760d233 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -70,7 +70,7 @@ func VerifyVoteExtSig(signature []byte, message votepersistenceTypes.VoteExtBody func extractPayload(txs [][]byte) (abcipb.Payload, error) { if len(txs) == 0 { - return abcipb.Payload{}, ErrEmptyBlock + return abcipb.Payload{}, nil } if !bytes.HasPrefix(txs[0], []byte(VoteExtMarker)) { diff --git a/abci/pre_blocker.go b/abci/pre_blocker.go index 5677638b..65ff1e19 100644 --- a/abci/pre_blocker.go +++ b/abci/pre_blocker.go @@ -12,7 +12,7 @@ func (h *AbciHandler) PreBlocker() sdk.PreBlocker { return func(ctx sdk.Context, req *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) { // If height is smaller than 4, we won't have any votes thus skip the proposal - if req.GetHeight() < 3 { + if req.GetHeight() < 4 { return &sdk.ResponsePreBlock{}, nil } diff --git a/abci/prepare_proposal.go b/abci/prepare_proposal.go index 0cde5942..2a6d1a10 100644 --- a/abci/prepare_proposal.go +++ b/abci/prepare_proposal.go @@ -10,8 +10,8 @@ func (h *AbciHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) { // to construct the payload we need to get the N-2th block's vote extensions. - // Hence, enabling prepare proposal on blocks < 3 will result in error. - if req.Height < 3 { + // Hence, enabling prepare proposal on blocks < 4 will result in error. + if req.Height < 4 { return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil } diff --git a/abci/process_proposal.go b/abci/process_proposal.go index 9f459434..d2ce3343 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -11,8 +11,8 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return func(ctx sdk.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) { - // If height is less than 3, we won't have any votes thus skip the proposal - if req.GetHeight() < 3 { + // If height is less than 4, we won't have any votes thus skip the proposal + if req.GetHeight() < 4 { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil } diff --git a/abci/types.go b/abci/types.go index 43ce10ce..f2376329 100644 --- a/abci/types.go +++ b/abci/types.go @@ -1,9 +1,5 @@ package vote_ext -import "errors" - const ActionsReducedRoot string = "pulsar" var VoteExtMarker string = "VOTEEXT:" - -var ErrEmptyBlock error = errors.New("this block has no transaction") From 2a9d07decb90b6789f15b7772afb3cddb0158775 Mon Sep 17 00:00:00 2001 From: korayakpinar Date: Sat, 2 May 2026 02:12:10 +0300 Subject: [PATCH 40/63] chore: regenerate openapi spec --- docs/static/openapi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/static/openapi.json b/docs/static/openapi.json index 43799f72..fe534475 100644 --- a/docs/static/openapi.json +++ b/docs/static/openapi.json @@ -1 +1 @@ -{"id":"github.com/node101-io/pulsar-chain","consumes":["application/json"],"produces":["application/json"],"swagger":"2.0","info":{"description":"Chain github.com/node101-io/pulsar-chain REST API","title":"HTTP API Console","contact":{"name":"github.com/node101-io/pulsar-chain"},"version":"version not set"},"paths":{"/node101-io/pulsar-chain/keyregistry/v1/get_user_cosmos_public_key/{user_mina_public_key}":{"get":{"tags":["Query"],"summary":"GetUserCosmosPublicKey Queries a list of GetUserCosmosPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserCosmosPublicKey","parameters":[{"type":"string","format":"byte","name":"user_mina_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_user_mina_public_key/{user_cosmos_public_key}":{"get":{"tags":["Query"],"summary":"GetUserMinaPublicKey Queries a list of GetUserMinaPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserMinaPublicKey","parameters":[{"type":"string","format":"byte","name":"user_cosmos_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_cosmos_pub_key/{validator_mina_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorCosmosPubKey Queries a list of GetValidatorCosmosPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorCosmosPubKey","parameters":[{"type":"string","format":"byte","name":"validator_mina_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_mina_pub_key/{validator_cosmos_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorMinaPubKey Queries a list of GetValidatorMinaPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorMinaPubKey","parameters":[{"type":"string","format":"byte","name":"validator_cosmos_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin8","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/pulsar/pulsar/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_Params","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsar.pulsar.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}}},"definitions":{"google.protobuf.Any":{"type":"object","properties":{"@type":{"type":"string"}},"additionalProperties":{}},"google.rpc.Status":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"details":{"type":"array","items":{"type":"object","$ref":"#/definitions/google.protobuf.Any"}},"message":{"type":"string"}}},"pulsar.pulsar.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsar.pulsar.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsar.pulsar.v1.Params"}}},"pulsarchain.keyregistry.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse":{"description":"QueryGetUserCosmosPublicKeyResponse defines the QueryGetUserCosmosPublicKeyResponse message.","type":"object","properties":{"user_cosmos_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse":{"description":"QueryGetUserMinaPublicKeyResponse defines the QueryGetUserMinaPublicKeyResponse message.","type":"object","properties":{"user_mina_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse":{"description":"QueryGetValidatorCosmosPubKeyResponse defines the QueryGetValidatorCosmosPubKeyResponse message.","type":"object","properties":{"validator_cosmos_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse":{"description":"QueryGetValidatorMinaPubKeyResponse defines the QueryGetValidatorMinaPubKeyResponse message.","type":"object","properties":{"validator_mina_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.keyregistry.v1.Params"}}}},"tags":[{"name":"Query"},{"name":"Msg"}]} \ No newline at end of file +{"id":"github.com/node101-io/pulsar-chain","consumes":["application/json"],"produces":["application/json"],"swagger":"2.0","info":{"description":"Chain github.com/node101-io/pulsar-chain REST API","title":"HTTP API Console","contact":{"name":"github.com/node101-io/pulsar-chain"},"version":"version not set"},"paths":{"/node101-io/pulsar-chain/keyregistry/v1/get_user_cosmos_public_key/{user_mina_public_key}":{"get":{"tags":["Query"],"summary":"GetUserCosmosPublicKey Queries a list of GetUserCosmosPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserCosmosPublicKey","parameters":[{"type":"string","format":"byte","name":"user_mina_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_user_mina_public_key/{user_cosmos_public_key}":{"get":{"tags":["Query"],"summary":"GetUserMinaPublicKey Queries a list of GetUserMinaPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserMinaPublicKey","parameters":[{"type":"string","format":"byte","name":"user_cosmos_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_cosmos_pub_key/{validator_mina_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorCosmosPubKey Queries a list of GetValidatorCosmosPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorCosmosPubKey","parameters":[{"type":"string","format":"byte","name":"validator_mina_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_mina_pub_key/{validator_cosmos_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorMinaPubKey Queries a list of GetValidatorMinaPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorMinaPubKey","parameters":[{"type":"string","format":"byte","name":"validator_cosmos_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin9","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin13","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/vote_ext_body_by_height/{block_height}":{"get":{"tags":["Query"],"summary":"VoteExtBodyByHeight Queries a list of VoteExtBodyByHeight items.","operationId":"GithubComnode101IopulsarChainQuery_VoteExtBodyByHeight","parameters":[{"type":"string","format":"int64","name":"block_height","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.VoteExtBody"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/pulsar/pulsar/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_Params","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsar.pulsar.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}}},"definitions":{"google.protobuf.Any":{"type":"object","properties":{"@type":{"type":"string"}},"additionalProperties":{}},"google.rpc.Status":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"details":{"type":"array","items":{"type":"object","$ref":"#/definitions/google.protobuf.Any"}},"message":{"type":"string"}}},"pulsar.pulsar.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsar.pulsar.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsar.pulsar.v1.Params"}}},"pulsarchain.keyregistry.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse":{"description":"QueryGetUserCosmosPublicKeyResponse defines the QueryGetUserCosmosPublicKeyResponse message.","type":"object","properties":{"user_cosmos_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse":{"description":"QueryGetUserMinaPublicKeyResponse defines the QueryGetUserMinaPublicKeyResponse message.","type":"object","properties":{"user_mina_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse":{"description":"QueryGetValidatorCosmosPubKeyResponse defines the QueryGetValidatorCosmosPubKeyResponse message.","type":"object","properties":{"validator_cosmos_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse":{"description":"QueryGetValidatorMinaPubKeyResponse defines the QueryGetValidatorMinaPubKeyResponse message.","type":"object","properties":{"validator_mina_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.keyregistry.v1.Params"}}},"pulsarchain.votepersistence.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.votepersistence.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.votepersistence.v1.Params"}}},"pulsarchain.votepersistence.v1.VoteExtBody":{"description":"VoteExtBody defines the VoteExtBody message.","type":"object","properties":{"actions_reduced_root":{"type":"string"},"current_block_height":{"type":"string","format":"int64"},"current_state_root":{"type":"string","format":"byte"},"next_validator_set_hash":{"type":"string","format":"byte"}}}},"tags":[{"name":"Query"},{"name":"Msg"}]} \ No newline at end of file From adc09407e6a9d31df667eb36f35726242dfc255c Mon Sep 17 00:00:00 2001 From: Yusuf Date: Sat, 2 May 2026 21:49:02 +0300 Subject: [PATCH 41/63] chore: read vote ext enable height from config and define an additional waiting height for vote extensions to be processed --- abci/extend_vote.go | 7 ++++++- abci/prepare_proposal.go | 9 ++++++--- abci/process_proposal.go | 8 ++++++-- abci/types.go | 8 +++++++- abci/verify_vote_ext.go | 10 +++++++++- 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/abci/extend_vote.go b/abci/extend_vote.go index b2a5e25d..5003e139 100644 --- a/abci/extend_vote.go +++ b/abci/extend_vote.go @@ -8,7 +8,12 @@ import ( func (h *AbciHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return func(ctx sdk.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) { - if req.GetHeight() < 3 { + cp := ctx.ConsensusParams() + if cp.Abci == nil { + return &abci.ResponseExtendVote{VoteExtension: []byte{}}, ErrUnableToReadConsensusParams + } + + if req.Height < cp.Abci.VoteExtensionsEnableHeight+AdditionalVoteExtHeight { return &abci.ResponseExtendVote{VoteExtension: []byte{}}, nil } diff --git a/abci/prepare_proposal.go b/abci/prepare_proposal.go index 2a6d1a10..e4243d64 100644 --- a/abci/prepare_proposal.go +++ b/abci/prepare_proposal.go @@ -9,9 +9,12 @@ func (h *AbciHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) { - // to construct the payload we need to get the N-2th block's vote extensions. - // Hence, enabling prepare proposal on blocks < 4 will result in error. - if req.Height < 4 { + cp := ctx.ConsensusParams() + if cp.Abci == nil { + return &abci.ResponsePrepareProposal{Txs: req.Txs}, ErrUnableToReadConsensusParams + } + + if req.Height < cp.Abci.VoteExtensionsEnableHeight+AdditionalVoteExtHeight+1 { return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil } diff --git a/abci/process_proposal.go b/abci/process_proposal.go index d2ce3343..6770564a 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -11,8 +11,12 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return func(ctx sdk.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) { - // If height is less than 4, we won't have any votes thus skip the proposal - if req.GetHeight() < 4 { + cp := ctx.ConsensusParams() + if cp.Abci == nil { + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, ErrUnableToReadConsensusParams + } + + if req.Height < cp.Abci.VoteExtensionsEnableHeight+AdditionalVoteExtHeight+1 { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil } diff --git a/abci/types.go b/abci/types.go index f2376329..a11249e1 100644 --- a/abci/types.go +++ b/abci/types.go @@ -1,5 +1,11 @@ package vote_ext +import "errors" + const ActionsReducedRoot string = "pulsar" -var VoteExtMarker string = "VOTEEXT:" +const VoteExtMarker string = "VOTEEXT:" + +const AdditionalVoteExtHeight int64 = 3 + +var ErrUnableToReadConsensusParams error = errors.New("unable to read consensus params") diff --git a/abci/verify_vote_ext.go b/abci/verify_vote_ext.go index 82cf9430..f4ed0cb5 100644 --- a/abci/verify_vote_ext.go +++ b/abci/verify_vote_ext.go @@ -9,7 +9,15 @@ import ( func (h *AbciHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandler { return func(ctx sdk.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) { - if req.GetHeight() < 3 { + + cp := ctx.ConsensusParams() + + if cp.Abci == nil { + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, ErrUnableToReadConsensusParams + } + + if req.Height < cp.Abci.VoteExtensionsEnableHeight+AdditionalVoteExtHeight { + if len(req.VoteExtension) == 0 { return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil } From 5e032955e981425acac4b5cd22dcb1ab50540ee1 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Tue, 5 May 2026 19:24:39 +0300 Subject: [PATCH 42/63] test: add tests for query VoteExtBodyByHeight --- x/votepersistence/keeper/keeper_test.go | 89 ++++++- .../query_vote_ext_body_by_height_test.go | 244 ++++++++++++++++++ 2 files changed, 319 insertions(+), 14 deletions(-) create mode 100644 x/votepersistence/keeper/query_vote_ext_body_by_height_test.go diff --git a/x/votepersistence/keeper/keeper_test.go b/x/votepersistence/keeper/keeper_test.go index d892a036..b686ba5c 100644 --- a/x/votepersistence/keeper/keeper_test.go +++ b/x/votepersistence/keeper/keeper_test.go @@ -1,47 +1,106 @@ package keeper_test import ( - "context" "testing" + "time" "cosmossdk.io/core/address" storetypes "cosmossdk.io/store/types" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + staking "github.com/cosmos/cosmos-sdk/x/staking" + 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" + "go.uber.org/mock/gomock" + keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" + keyregistrymodule "github.com/node101-io/pulsar-chain/x/keyregistry/module" + keyregistrytypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" module "github.com/node101-io/pulsar-chain/x/votepersistence/module" "github.com/node101-io/pulsar-chain/x/votepersistence/types" ) +var ( + bondedAcc = authtypes.NewEmptyModuleAccount(stakingtypes.BondedPoolName) + notBondedAcc = authtypes.NewEmptyModuleAccount(stakingtypes.NotBondedPoolName) +) + type fixture struct { - ctx context.Context - keeper keeper.Keeper - addressCodec address.Codec + ctx sdk.Context + keeper keeper.Keeper + keyregistryKeeper keyregistrykeeper.Keeper + stakingKeeper *stakingkeeper.Keeper + addressCodec address.Codec } func initFixture(t *testing.T) *fixture { t.Helper() - encCfg := moduletestutil.MakeTestEncodingConfig(module.AppModule{}) + encCfg := moduletestutil.MakeTestEncodingConfig( + module.AppModule{}, + keyregistrymodule.AppModule{}, + staking.AppModuleBasic{}, + ) addressCodec := addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) - storeKey := storetypes.NewKVStoreKey(types.StoreKey) + validatorAddressCodec := addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()) + consensusAddressCodec := addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()) - storeService := runtime.NewKVStoreService(storeKey) - ctx := testutil.DefaultContextWithDB(t, storeKey, storetypes.NewTransientStoreKey("transient_test")).Ctx + storeKeys := storetypes.NewKVStoreKeys(types.StoreKey, keyregistrytypes.StoreKey, stakingtypes.StoreKey) + transientKeys := storetypes.NewTransientStoreKeys("transient_test") + ctx := testutil.DefaultContextWithKeys(storeKeys, transientKeys, nil).WithBlockHeader(tmproto.Header{ + Time: time.Now(), + }) authority := authtypes.NewModuleAddress(types.GovModuleName) + ctrl := gomock.NewController(t) + accountKeeper := stakingtestutil.NewMockAccountKeeper(ctrl) + accountKeeper.EXPECT().GetModuleAddress(stakingtypes.BondedPoolName).Return(bondedAcc.GetAddress()).AnyTimes() + accountKeeper.EXPECT().GetModuleAddress(stakingtypes.NotBondedPoolName).Return(notBondedAcc.GetAddress()).AnyTimes() + accountKeeper.EXPECT().AddressCodec().Return(addressCodec).AnyTimes() + + bankKeeper := stakingtestutil.NewMockBankKeeper(ctrl) + + stakingStoreService := runtime.NewKVStoreService(storeKeys[stakingtypes.StoreKey]) + stakingKeeper := stakingkeeper.NewKeeper( + encCfg.Codec, + stakingStoreService, + accountKeeper, + bankKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + validatorAddressCodec, + consensusAddressCodec, + ) + if err := stakingKeeper.SetParams(ctx, stakingtypes.DefaultParams()); err != nil { + t.Fatalf("failed to set staking params: %v", err) + } + + keyregistryStoreService := runtime.NewKVStoreService(storeKeys[keyregistrytypes.StoreKey]) + keyregistryKeeper := keyregistrykeeper.NewKeeper( + keyregistryStoreService, + encCfg.Codec, + addressCodec, + authority, + ) + if err := keyregistryKeeper.Params.Set(ctx, keyregistrytypes.DefaultParams()); err != nil { + t.Fatalf("failed to set keyregistry params: %v", err) + } + + votepersistenceStoreService := runtime.NewKVStoreService(storeKeys[types.StoreKey]) k := keeper.NewKeeper( - storeService, + votepersistenceStoreService, encCfg.Codec, addressCodec, - nil, - nil, + stakingKeeper, + keyregistryKeeper, authority, ) @@ -51,8 +110,10 @@ func initFixture(t *testing.T) *fixture { } return &fixture{ - ctx: ctx, - keeper: k, - addressCodec: addressCodec, + ctx: ctx, + keeper: k, + keyregistryKeeper: keyregistryKeeper, + stakingKeeper: stakingKeeper, + addressCodec: addressCodec, } } diff --git a/x/votepersistence/keeper/query_vote_ext_body_by_height_test.go b/x/votepersistence/keeper/query_vote_ext_body_by_height_test.go new file mode 100644 index 00000000..b3cb5b20 --- /dev/null +++ b/x/votepersistence/keeper/query_vote_ext_body_by_height_test.go @@ -0,0 +1,244 @@ +package keeper_test + +import ( + "math/big" + "testing" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/node101-io/mina-signer-go/constants" + "github.com/node101-io/mina-signer-go/field" + "github.com/node101-io/mina-signer-go/keys" + "github.com/node101-io/mina-signer-go/poseidon" + keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" + keyregistrytypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" + "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" + "github.com/node101-io/pulsar-chain/x/votepersistence/types" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var queryMockCosmosSignature = []byte("cosmosSig") +var queryMockMinaSignature = []byte("minaSig") + +func newBondedValidator(t *testing.T, power int64) stakingtypes.Validator { + t.Helper() + + consPubKey := ed25519.GenPrivKey().PubKey() + validator, err := stakingtypes.NewValidator( + sdk.ValAddress(consPubKey.Address()).String(), + consPubKey, + stakingtypes.Description{}, + ) + require.NoError(t, err) + + validator = validator.UpdateStatus(stakingtypes.Bonded) + validator.Tokens = sdk.TokensFromConsensusPower(power, sdk.DefaultPowerReduction) + + return validator +} + +func generateMinaPublicKey(t *testing.T, seed [32]byte) []byte { + t.Helper() + + minaPrivKey := keys.NewPrivateKeyFromBytes(seed) + minaPubKey, err := minaPrivKey.ToPublicKey().Marshal() + require.NoError(t, err) + + return minaPubKey +} + +func registerValidatorKeys(t *testing.T, f *fixture, cosmosPubKey cryptotypes.PubKey, minaPubKey []byte) { + t.Helper() + + ms := keyregistrykeeper.NewMsgServerImpl(f.keyregistryKeeper) + creatorAddr := sdk.AccAddress(cosmosPubKey.Address()) + + _, err := ms.RegisterKeys(f.ctx, &keyregistrytypes.MsgRegisterKeys{ + Creator: creatorAddr.String(), + CosmosSignature: queryMockCosmosSignature, + MinaSignature: queryMockMinaSignature, + CosmosPublicKey: cosmosPubKey.Bytes(), + MinaPublicKey: minaPubKey, + ActorType: keyregistrytypes.ActorType_VALIDATOR, + }) + require.NoError(t, err) +} + +func calculateExpectedValidatorSetRoot(t *testing.T, validatorSet []stakingtypes.Validator, cosmosToMina map[string][]byte) []byte { + t.Helper() + + poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) + merkleRoot := poseidonHash.Hash([]*big.Int{big.NewInt(0)}) + + for _, validator := range validatorSet { + cosmosValidatorPubKey, err := validator.ConsPubKey() + require.NoError(t, err) + + minaPubKeyBz, ok := cosmosToMina[string(cosmosValidatorPubKey.Bytes())] + require.True(t, ok) + + var minaPubKey keys.PublicKey + require.NoError(t, minaPubKey.Unmarshal(minaPubKeyBz)) + + input := []*big.Int{minaPubKey.X} + if minaPubKey.IsOdd { + input = append(input, big.NewInt(1)) + } else { + input = append(input, big.NewInt(0)) + } + input = append(input, big.NewInt(validator.ConsensusPower(sdk.DefaultPowerReduction))) + + hashOfValidator := poseidonHash.Hash(input) + merkleRoot = poseidonHash.Hash([]*big.Int{merkleRoot, hashOfValidator}) + } + + return merkleRoot.Bytes() +} + +// TestVoteExtBodyByHeightInvalidArgumentFail verifies that VoteExtBodyByHeight +// returns an InvalidArgument error when called with a nil request. +func TestVoteExtBodyByHeightInvalidArgumentFail(t *testing.T) { + f := initFixture(t) + + qs := keeper.NewQueryServerImpl(f.keeper) + params := types.DefaultParams() + require.NoError(t, f.keeper.Params.Set(f.ctx, params)) + + _, err := qs.VoteExtBodyByHeight(f.ctx, nil) + require.Error(t, err) + + st, _ := status.FromError(err) + require.Equal(t, codes.InvalidArgument, st.Code()) +} + +// TestVoteExtBodyByHeightEarlyBlockInvalidArgumentFail verifies that +// VoteExtBodyByHeight rejects requests for block heights smaller than 4. +func TestVoteExtBodyByHeightEarlyBlockInvalidArgumentFail(t *testing.T) { + f := initFixture(t) + + qs := keeper.NewQueryServerImpl(f.keeper) + params := types.DefaultParams() + require.NoError(t, f.keeper.Params.Set(f.ctx, params)) + + _, err := qs.VoteExtBodyByHeight(f.ctx, &types.QueryVoteExtBodyByHeightRequest{ + BlockHeight: 3, + }) + require.Error(t, err) + + st, _ := status.FromError(err) + require.Equal(t, codes.InvalidArgument, st.Code()) +} + +// TestVoteExtBodyByHeightRequestedBlockNotAvailable verifies that +// VoteExtBodyByHeight rejects requests for the current or future block. +func TestVoteExtBodyByHeightRequestedBlockNotAvailable(t *testing.T) { + f := initFixture(t) + ctx := f.ctx.WithBlockHeight(10) + + qs := keeper.NewQueryServerImpl(f.keeper) + params := types.DefaultParams() + require.NoError(t, f.keeper.Params.Set(f.ctx, params)) + + _, err := qs.VoteExtBodyByHeight(ctx, &types.QueryVoteExtBodyByHeightRequest{ + BlockHeight: 10, + }) + require.Error(t, err) + + st, _ := status.FromError(err) + require.Equal(t, codes.InvalidArgument, st.Code()) +} + +// TestVoteExtBodyByHeightSuccess verifies that VoteExtBodyByHeight constructs +// the expected body using real staking historical info and registered validator +// Mina keys. +func TestVoteExtBodyByHeightSuccess(t *testing.T) { + f := initFixture(t) + + validatorOne := newBondedValidator(t, 25) + validatorTwo := newBondedValidator(t, 10) + + consPubKeyOne, err := validatorOne.ConsPubKey() + require.NoError(t, err) + consPubKeyTwo, err := validatorTwo.ConsPubKey() + require.NoError(t, err) + + minaPubKeyOne := generateMinaPublicKey(t, [32]byte{ + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + }) + minaPubKeyTwo := generateMinaPublicKey(t, [32]byte{ + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + }) + + registerValidatorKeys(t, f, consPubKeyOne, minaPubKeyOne) + registerValidatorKeys(t, f, consPubKeyTwo, minaPubKeyTwo) + + require.NoError(t, f.stakingKeeper.SetHistoricalInfo(f.ctx, 6, &stakingtypes.HistoricalInfo{ + Header: tmproto.Header{AppHash: []byte("current-state-root")}, + })) + require.NoError(t, f.stakingKeeper.SetHistoricalInfo(f.ctx, 7, &stakingtypes.HistoricalInfo{ + Valset: []stakingtypes.Validator{validatorOne, validatorTwo}, + })) + + cosmosToMina := map[string][]byte{ + string(consPubKeyOne.Bytes()): minaPubKeyOne, + string(consPubKeyTwo.Bytes()): minaPubKeyTwo, + } + + ctx := f.ctx.WithBlockHeight(10) + qs := keeper.NewQueryServerImpl(f.keeper) + params := types.DefaultParams() + require.NoError(t, f.keeper.Params.Set(f.ctx, params)) + + queryResp, err := qs.VoteExtBodyByHeight(ctx, &types.QueryVoteExtBodyByHeightRequest{ + BlockHeight: 8, + }) + require.NoError(t, err) + require.NotNil(t, queryResp) + + require.Equal(t, &types.VoteExtBody{ + NextValidatorSetHash: calculateExpectedValidatorSetRoot(t, []stakingtypes.Validator{validatorOne, validatorTwo}, cosmosToMina), + CurrentStateRoot: []byte("current-state-root"), + CurrentBlockHeight: 7, + ActionsReducedRoot: keeper.ActionsReducedRoot, + }, queryResp) +} + +// TestVoteExtBodyByHeightValidatorMinaKeyNotFound verifies that +// VoteExtBodyByHeight returns a NotFound error when a validator is missing a +// registered Mina key. +func TestVoteExtBodyByHeightValidatorMinaKeyNotFound(t *testing.T) { + f := initFixture(t) + + validator := newBondedValidator(t, 15) + + require.NoError(t, f.stakingKeeper.SetHistoricalInfo(f.ctx, 6, &stakingtypes.HistoricalInfo{ + Header: tmproto.Header{AppHash: []byte("current-state-root")}, + })) + require.NoError(t, f.stakingKeeper.SetHistoricalInfo(f.ctx, 7, &stakingtypes.HistoricalInfo{ + Valset: []stakingtypes.Validator{validator}, + })) + + ctx := f.ctx.WithBlockHeight(10) + qs := keeper.NewQueryServerImpl(f.keeper) + params := types.DefaultParams() + require.NoError(t, f.keeper.Params.Set(f.ctx, params)) + + _, err := qs.VoteExtBodyByHeight(ctx, &types.QueryVoteExtBodyByHeightRequest{ + BlockHeight: 8, + }) + require.Error(t, err) + + st, _ := status.FromError(err) + require.Equal(t, codes.NotFound, st.Code()) +} From 75559c053a4b3cc0d5895545888b99ea749ba922 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Tue, 5 May 2026 21:26:37 +0300 Subject: [PATCH 43/63] chore: remove unnecessary verifier, fix returned errors and verify vote extensions before checking for stake power --- abci/helpers.go | 84 ++++++++++++++++++++-------------------- abci/process_proposal.go | 7 +--- abci/types.go | 2 + abci/verify_vote_ext.go | 7 ++-- 4 files changed, 50 insertions(+), 50 deletions(-) diff --git a/abci/helpers.go b/abci/helpers.go index 1760d233..cd946c87 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -2,13 +2,12 @@ package vote_ext import ( "bytes" - "context" "encoding/hex" - "fmt" "math/big" "sort" abci "github.com/cometbft/cometbft/abci/types" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/node101-io/mina-signer-go/constants" @@ -17,7 +16,7 @@ import ( "github.com/node101-io/mina-signer-go/poseidon" minasignature "github.com/node101-io/mina-signer-go/signature" abcipb "github.com/node101-io/pulsar-chain/api/pulsarchain/abci" - "github.com/node101-io/pulsar-chain/x/votepersistence/types" + "github.com/node101-io/pulsar-chain/x/keyregistry/types" votepersistenceTypes "github.com/node101-io/pulsar-chain/x/votepersistence/types" ) @@ -31,7 +30,7 @@ func (s *SecondaryKey) SignVoteExtBody(voteExtBody votepersistenceTypes.VoteExtB return nil } - sig, err := s.SecretKey.SignMessage(hex.EncodeToString(msg), "testnet") + sig, err := s.SecretKey.SignMessage(hex.EncodeToString(msg), NetworkID) if err != nil { return nil } @@ -44,7 +43,7 @@ func (s *SecondaryKey) SignVoteExtBody(voteExtBody votepersistenceTypes.VoteExtB return bz } -func VerifyVoteExtSig(signature []byte, message votepersistenceTypes.VoteExtBody, minaKey []byte, reducedRoot string) bool { +func verifyVoteExtSig(signature []byte, message votepersistenceTypes.VoteExtBody, minaKey []byte, reducedRoot string) bool { if message.ActionsReducedRoot != reducedRoot { return false } @@ -64,7 +63,7 @@ func VerifyVoteExtSig(signature []byte, message votepersistenceTypes.VoteExtBody return false } - return pubKey.VerifyMessage(&sig, hex.EncodeToString(msg), "testnet") + return pubKey.VerifyMessage(&sig, hex.EncodeToString(msg), NetworkID) } func extractPayload(txs [][]byte) (abcipb.Payload, error) { @@ -74,7 +73,7 @@ func extractPayload(txs [][]byte) (abcipb.Payload, error) { } if !bytes.HasPrefix(txs[0], []byte(VoteExtMarker)) { - return abcipb.Payload{}, types.ErrVoteExtMarkerNotFound + return abcipb.Payload{}, votepersistenceTypes.ErrVoteExtMarkerNotFound } voteExtensionTx := txs[0][len([]byte(VoteExtMarker)):] @@ -88,37 +87,6 @@ func extractPayload(txs [][]byte) (abcipb.Payload, error) { return pl, nil } -func (h *AbciHandler) verifyVoteExtension(ctx context.Context, pl abcipb.Payload, body votepersistenceTypes.VoteExtBody) error { - - for _, vote := range pl.Votes { - - pk, err := hex.DecodeString(vote.ConsensusPublicKey) - if err != nil { - return err - } - - exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, pk) - if err != nil { - return err - } - if !exists { - return fmt.Errorf("") - } - - minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, pk) - if err != nil { - return err - } - - if !VerifyVoteExtSig(vote.VoteExtension, body, minaKey, ActionsReducedRoot) { - return types.ErrInvalidVoteExtension.Wrap("invalid signature") - } - - } - - return nil -} - // Use if you need the validator set of block < N where N is the current block number. func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]stakingTypes.ValidatorI, error) { @@ -236,7 +204,7 @@ func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []staki } -func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl abcipb.Payload) (bool, error) { +func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl abcipb.Payload, body votepersistenceTypes.VoteExtBody) (bool, error) { var signedStakePower int64 var currentValidatorStakePower int64 @@ -265,10 +233,36 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl abc } for _, vote := range pl.Votes { + validatorInfo, ok := valInfoMap[vote.ConsensusPublicKey] - if ok { - signedStakePower += validatorInfo.GetConsensusPower(sdk.DefaultPowerReduction) + if !ok { + continue + } + + pk, err := hex.DecodeString(vote.ConsensusPublicKey) + if err != nil { + return false, err + } + + exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, pk) + if err != nil { + return false, err + } + if !exists { + return false, types.ErrValidatorNotRegistered + } + + minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, pk) + if err != nil { + return false, err } + + if !verifyVoteExtSig(vote.VoteExtension, body, minaKey, ActionsReducedRoot) { + return false, votepersistenceTypes.ErrInvalidVoteExtension.Wrap("invalid signature") + } + + signedStakePower += validatorInfo.GetConsensusPower(sdk.DefaultPowerReduction) + } if signedStakePower*3 < currentValidatorStakePower*2 { return false, nil @@ -348,6 +342,14 @@ func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteE continue } + if vote.BlockIdFlag != tmproto.BlockIDFlagCommit { + continue + } + + if len(vote.VoteExtension) == 0 { + continue + } + cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, vote.Validator.Address) if err != nil { return abcipb.Payload{}, err diff --git a/abci/process_proposal.go b/abci/process_proposal.go index 6770564a..d7ec60e7 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -30,12 +30,7 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } - err = h.verifyVoteExtension(ctx, pl, body) - if err != nil { - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err - } - - isEnoughStakePower, err := h.checkStakePower(ctx, req.GetHeight(), pl) + isEnoughStakePower, err := h.checkStakePower(ctx, req.GetHeight(), pl, body) if err != nil { return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } diff --git a/abci/types.go b/abci/types.go index a11249e1..5ceb8bd7 100644 --- a/abci/types.go +++ b/abci/types.go @@ -8,4 +8,6 @@ const VoteExtMarker string = "VOTEEXT:" const AdditionalVoteExtHeight int64 = 3 +const NetworkID string = "testnet" + var ErrUnableToReadConsensusParams error = errors.New("unable to read consensus params") diff --git a/abci/verify_vote_ext.go b/abci/verify_vote_ext.go index f4ed0cb5..df026643 100644 --- a/abci/verify_vote_ext.go +++ b/abci/verify_vote_ext.go @@ -5,6 +5,7 @@ import ( abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/node101-io/pulsar-chain/x/keyregistry/types" ) func (h *AbciHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandler { @@ -36,7 +37,7 @@ func (h *AbciHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandle } if !exists { - return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, types.ErrValidatorNotRegistered } minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, cosmosValidatorPubKey) @@ -49,9 +50,9 @@ func (h *AbciHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandle return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err } - sigValidity := VerifyVoteExtSig(req.VoteExtension, body, minaKey, ActionsReducedRoot) + sigValidity := verifyVoteExtSig(req.VoteExtension, body, minaKey, ActionsReducedRoot) if !sigValidity { - return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, err + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, types.ErrInvalidSignature } return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil From 546ce7a52b602f67b73b0e03f4aa0c4036a3c8a9 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Tue, 5 May 2026 21:55:12 +0300 Subject: [PATCH 44/63] chore: add an err for not enough stake power case --- abci/process_proposal.go | 4 +--- abci/types.go | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/abci/process_proposal.go b/abci/process_proposal.go index d7ec60e7..7e8e0a76 100644 --- a/abci/process_proposal.go +++ b/abci/process_proposal.go @@ -1,8 +1,6 @@ package vote_ext import ( - "fmt" - abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -36,7 +34,7 @@ func (h *AbciHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { } if !isEnoughStakePower { - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, fmt.Errorf("") + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, ErrNotEnoughStakePower } // Vote extension successfully verified diff --git a/abci/types.go b/abci/types.go index 5ceb8bd7..d23beba7 100644 --- a/abci/types.go +++ b/abci/types.go @@ -11,3 +11,5 @@ const AdditionalVoteExtHeight int64 = 3 const NetworkID string = "testnet" var ErrUnableToReadConsensusParams error = errors.New("unable to read consensus params") +var ErrInvalidPayload error = errors.New("invalid payload") +var ErrNotEnoughStakePower error = errors.New("not enough stake power signed the vote extension") From d3b000b860d0292bb0a2ca3b7abf305d26fe7c26 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 6 May 2026 18:19:28 +0300 Subject: [PATCH 45/63] feat: customizable number of validators --- scripts/setup_local_testnet.sh | 245 ++++++++++++++++---------- scripts/setup_local_testnet_helper.py | 52 ++++++ 2 files changed, 202 insertions(+), 95 deletions(-) diff --git a/scripts/setup_local_testnet.sh b/scripts/setup_local_testnet.sh index c31094d9..58c0a0db 100755 --- a/scripts/setup_local_testnet.sh +++ b/scripts/setup_local_testnet.sh @@ -8,32 +8,25 @@ PYTHON_HELPER="$SCRIPT_DIR/setup_local_testnet_helper.py" GO_HELPER="$SCRIPT_DIR/derive_mina_pub.go" LEGACY_CHAIN_HOME="${CHAIN_HOME:-$HOME/.pulsar}" -NODE1_HOME="${NODE1_HOME:-$HOME/.pulsar-node1}" -NODE2_HOME="${NODE2_HOME:-$HOME/.pulsar-node2}" CHAIN_ID="${CHAIN_ID:-mytestnet}" -NODE1_MONIKER="${NODE1_MONIKER:-node1}" -NODE2_MONIKER="${NODE2_MONIKER:-node2}" -NODE1_KEY_NAME="${NODE1_KEY_NAME:-validator1}" -NODE2_KEY_NAME="${NODE2_KEY_NAME:-validator2}" KEYRING_BACKEND="${KEYRING_BACKEND:-test}" DENOM="${DENOM:-pmina}" STAKE_AMOUNT="${STAKE_AMOUNT:-1000000000}" BOND_AMOUNT="${BOND_AMOUNT:-100000000}" MIN_GAS_PRICE="${MIN_GAS_PRICE:-0.0001pmina}" -VOTE_EXT_ENABLE_HEIGHT="${VOTE_EXT_ENABLE_HEIGHT:-3}" -NODE1_MINA_PRIV_KEY="${NODE1_MINA_PRIV_KEY:-ES17xFroE2/QOa9yCLXsQ9sJMeIUVwr2ZXcdWGjNLlM=}" -NODE2_MINA_PRIV_KEY="${NODE2_MINA_PRIV_KEY:-PKeRXivUb4gZ/nMKxUK5beEnVJwIrzN71mAf7JVKsng=}" -NODE1_P2P_PORT="${NODE1_P2P_PORT:-26656}" -NODE1_RPC_PORT="${NODE1_RPC_PORT:-26657}" -NODE2_P2P_PORT="${NODE2_P2P_PORT:-26666}" -NODE2_RPC_PORT="${NODE2_RPC_PORT:-26667}" -NODE1_GRPC_PORT="${NODE1_GRPC_PORT:-9090}" -NODE2_GRPC_PORT="${NODE2_GRPC_PORT:-9091}" -NODE1_API_PORT="${NODE1_API_PORT:-1317}" -NODE2_API_PORT="${NODE2_API_PORT:-1318}" +VOTE_EXT_ENABLE_HEIGHT="${VOTE_EXT_ENABLE_HEIGHT:-1}" BIN_DIR="${BIN_DIR:-$HOME/go/bin}" BINARY_PATH="${BINARY_PATH:-$BIN_DIR/pulsard}" COMPAT_BINARY_PATH="${COMPAT_BINARY_PATH:-$BIN_DIR/pulsar-chaind}" +DEFAULT_NODE1_MINA_PRIV_KEY="ES17xFroE2/QOa9yCLXsQ9sJMeIUVwr2ZXcdWGjNLlM=" +DEFAULT_NODE2_MINA_PRIV_KEY="PKeRXivUb4gZ/nMKxUK5beEnVJwIrzN71mAf7JVKsng=" + +if (( $# > 1 )); then + echo "usage: $0 [validator-count]" >&2 + exit 1 +fi + +VALIDATOR_COUNT="${1:-${VALIDATOR_COUNT:-2}}" require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then @@ -50,6 +43,33 @@ read_consensus_pub_key() { python3 "$PYTHON_HELPER" read-consensus-pub-key --priv-validator-key "$1" } +generate_default_mina_priv_key() { + python3 "$PYTHON_HELPER" generate-default-mina-priv-key --index "$1" +} + +default_node_mina_priv_key() { + local index="$1" + + case "$index" in + 1) printf '%s\n' "$DEFAULT_NODE1_MINA_PRIV_KEY" ;; + 2) printf '%s\n' "$DEFAULT_NODE2_MINA_PRIV_KEY" ;; + *) generate_default_mina_priv_key "$index" ;; + esac +} + +validate_mina_priv_key() { + python3 "$PYTHON_HELPER" validate-mina-priv-key --index "$1" --mina-priv-key "$2" +} + +get_node_setting() { + local index="$1" + local suffix="$2" + local default_value="$3" + local var_name="NODE${index}_${suffix}" + + printf '%s\n' "${!var_name:-$default_value}" +} + configure_node() { local home="$1" local rpc_port="$2" @@ -74,17 +94,55 @@ configure_node() { --mina-priv-key "$mina_priv_key" } +build_persistent_peers() { + local current_index="$1" + local i + local -a peers=() + + for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + if (( i == current_index )); then + continue + fi + + peers+=("${NODE_IDS[i]}@127.0.0.1:${NODE_P2P_PORTS[i]}") + done + + local IFS=, + printf '%s\n' "${peers[*]}" +} + require_cmd go require_cmd python3 -NODE1_MINA_PUB_KEY="$(derive_mina_pub_key "$NODE1_MINA_PRIV_KEY")" -NODE2_MINA_PUB_KEY="$(derive_mina_pub_key "$NODE2_MINA_PRIV_KEY")" +if ! [[ "$VALIDATOR_COUNT" =~ ^[0-9]+$ ]] || (( VALIDATOR_COUNT < 1 )); then + echo "validator count must be a positive integer, got: $VALIDATOR_COUNT" >&2 + exit 1 +fi -NODE1_GENESIS_FILE="$NODE1_HOME/config/genesis.json" -NODE2_GENESIS_FILE="$NODE2_HOME/config/genesis.json" +declare -a NODE_HOMES NODE_MONIKERS NODE_KEY_NAMES NODE_MINA_PRIV_KEYS NODE_MINA_PUB_KEYS +declare -a NODE_P2P_PORTS NODE_RPC_PORTS NODE_GRPC_PORTS NODE_API_PORTS +declare -a NODE_GENESIS_FILES NODE_ADDRS NODE_COSMOS_PUB_KEYS NODE_IDS + +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + NODE_HOMES[i]="$(get_node_setting "$i" "HOME" "$HOME/.pulsar-node${i}")" + NODE_MONIKERS[i]="$(get_node_setting "$i" "MONIKER" "node${i}")" + NODE_KEY_NAMES[i]="$(get_node_setting "$i" "KEY_NAME" "validator${i}")" + NODE_MINA_PRIV_KEYS[i]="$(get_node_setting "$i" "MINA_PRIV_KEY" "$(default_node_mina_priv_key "$i")")" + validate_mina_priv_key "$i" "${NODE_MINA_PRIV_KEYS[i]}" + NODE_P2P_PORTS[i]="$(get_node_setting "$i" "P2P_PORT" "$((26656 + ((i - 1) * 10)))")" + NODE_RPC_PORTS[i]="$(get_node_setting "$i" "RPC_PORT" "$((26657 + ((i - 1) * 10)))")" + NODE_GRPC_PORTS[i]="$(get_node_setting "$i" "GRPC_PORT" "$((9090 + i - 1))")" + NODE_API_PORTS[i]="$(get_node_setting "$i" "API_PORT" "$((1317 + i - 1))")" + NODE_MINA_PUB_KEYS[i]="$(derive_mina_pub_key "${NODE_MINA_PRIV_KEYS[i]}")" + NODE_GENESIS_FILES[i]="${NODE_HOMES[i]}/config/genesis.json" +done + +PRIMARY_NODE_INDEX=1 +PRIMARY_HOME="${NODE_HOMES[PRIMARY_NODE_INDEX]}" +PRIMARY_GENESIS_FILE="${NODE_GENESIS_FILES[PRIMARY_NODE_INDEX]}" echo "==> Cleaning previous homes..." -rm -rf "$LEGACY_CHAIN_HOME" "$NODE1_HOME" "$NODE2_HOME" +rm -rf "$LEGACY_CHAIN_HOME" "${NODE_HOMES[@]}" echo "==> Building binary..." mkdir -p "$BIN_DIR" @@ -98,101 +156,98 @@ if [[ "$COMPAT_BINARY_PATH" != "$BINARY_PATH" ]]; then fi echo "==> Initializing nodes..." -"$BINARY_PATH" init "$NODE1_MONIKER" --chain-id "$CHAIN_ID" --home "$NODE1_HOME" >/dev/null 2>&1 -"$BINARY_PATH" init "$NODE2_MONIKER" --chain-id "$CHAIN_ID" --home "$NODE2_HOME" >/dev/null 2>&1 +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + "$BINARY_PATH" init "${NODE_MONIKERS[i]}" --chain-id "$CHAIN_ID" --home "${NODE_HOMES[i]}" >/dev/null 2>&1 +done echo "==> Setting vote extension enable height..." python3 "$PYTHON_HELPER" set-vote-extension-height \ - --genesis "$NODE1_GENESIS_FILE" \ + --genesis "$PRIMARY_GENESIS_FILE" \ --height "$VOTE_EXT_ENABLE_HEIGHT" echo "==> Creating validator keys..." -"$BINARY_PATH" keys add "$NODE1_KEY_NAME" --home "$NODE1_HOME" --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 -"$BINARY_PATH" keys add "$NODE2_KEY_NAME" --home "$NODE2_HOME" --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 - -NODE1_ADDR="$("$BINARY_PATH" keys show "$NODE1_KEY_NAME" --address --home "$NODE1_HOME" --keyring-backend "$KEYRING_BACKEND")" -NODE2_ADDR="$("$BINARY_PATH" keys show "$NODE2_KEY_NAME" --address --home "$NODE2_HOME" --keyring-backend "$KEYRING_BACKEND")" +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + "$BINARY_PATH" keys add "${NODE_KEY_NAMES[i]}" --home "${NODE_HOMES[i]}" --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 + NODE_ADDRS[i]="$("$BINARY_PATH" keys show "${NODE_KEY_NAMES[i]}" --address --home "${NODE_HOMES[i]}" --keyring-backend "$KEYRING_BACKEND")" +done echo "==> Adding genesis accounts..." -"$BINARY_PATH" genesis add-genesis-account "$NODE1_ADDR" "${STAKE_AMOUNT}${DENOM}" --home "$NODE1_HOME" >/dev/null 2>&1 -"$BINARY_PATH" genesis add-genesis-account "$NODE2_ADDR" "${STAKE_AMOUNT}${DENOM}" --home "$NODE1_HOME" >/dev/null 2>&1 - -echo "==> Creating gentx for ${NODE1_KEY_NAME}..." -"$BINARY_PATH" genesis gentx "$NODE1_KEY_NAME" "${BOND_AMOUNT}${DENOM}" \ - --chain-id "$CHAIN_ID" \ - --home "$NODE1_HOME" \ - --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 - -echo "==> Copying shared genesis to node2..." -cp "$NODE1_GENESIS_FILE" "$NODE2_GENESIS_FILE" +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + "$BINARY_PATH" genesis add-genesis-account "${NODE_ADDRS[i]}" "${STAKE_AMOUNT}${DENOM}" --home "$PRIMARY_HOME" >/dev/null 2>&1 +done + +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + if (( i > PRIMARY_NODE_INDEX )); then + echo "==> Copying shared genesis to ${NODE_MONIKERS[i]}..." + cp "$PRIMARY_GENESIS_FILE" "${NODE_GENESIS_FILES[i]}" + fi -echo "==> Creating gentx for ${NODE2_KEY_NAME}..." -"$BINARY_PATH" genesis gentx "$NODE2_KEY_NAME" "${BOND_AMOUNT}${DENOM}" \ - --chain-id "$CHAIN_ID" \ - --home "$NODE2_HOME" \ - --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 + echo "==> Creating gentx for ${NODE_KEY_NAMES[i]}..." + "$BINARY_PATH" genesis gentx "${NODE_KEY_NAMES[i]}" "${BOND_AMOUNT}${DENOM}" \ + --chain-id "$CHAIN_ID" \ + --home "${NODE_HOMES[i]}" \ + --keyring-backend "$KEYRING_BACKEND" >/dev/null 2>&1 +done echo "==> Collecting gentxs..." -cp "$NODE2_HOME"/config/gentx/*.json "$NODE1_HOME/config/gentx/" -"$BINARY_PATH" genesis collect-gentxs --home "$NODE1_HOME" >/dev/null 2>&1 +for ((i = PRIMARY_NODE_INDEX + 1; i <= VALIDATOR_COUNT; i++)); do + cp "${NODE_HOMES[i]}"/config/gentx/*.json "$PRIMARY_HOME/config/gentx/" +done +"$BINARY_PATH" genesis collect-gentxs --home "$PRIMARY_HOME" >/dev/null 2>&1 -NODE1_COSMOS_PUB_KEY="$(read_consensus_pub_key "$NODE1_HOME/config/priv_validator_key.json")" -NODE2_COSMOS_PUB_KEY="$(read_consensus_pub_key "$NODE2_HOME/config/priv_validator_key.json")" +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + NODE_COSMOS_PUB_KEYS[i]="$(read_consensus_pub_key "${NODE_HOMES[i]}/config/priv_validator_key.json")" +done echo "==> Patching keyregistry validator key pairs..." -python3 "$PYTHON_HELPER" patch-keyregistry \ - --genesis "$NODE1_GENESIS_FILE" \ - --cosmos-key "$NODE1_COSMOS_PUB_KEY" \ - --mina-pub-key "$NODE1_MINA_PUB_KEY" \ - --cosmos-key "$NODE2_COSMOS_PUB_KEY" \ - --mina-pub-key "$NODE2_MINA_PUB_KEY" >/dev/null +patch_keyregistry_args=(patch-keyregistry --genesis "$PRIMARY_GENESIS_FILE") +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + patch_keyregistry_args+=(--cosmos-key "${NODE_COSMOS_PUB_KEYS[i]}") + patch_keyregistry_args+=(--mina-pub-key "${NODE_MINA_PUB_KEYS[i]}") +done +python3 "$PYTHON_HELPER" "${patch_keyregistry_args[@]}" >/dev/null echo "==> Validating final genesis..." -"$BINARY_PATH" genesis validate-genesis --home "$NODE1_HOME" >/dev/null 2>&1 - -echo "==> Copying final genesis to node2..." -cp "$NODE1_GENESIS_FILE" "$NODE2_GENESIS_FILE" - -NODE1_ID="$("$BINARY_PATH" tendermint show-node-id --home "$NODE1_HOME")" -NODE2_ID="$("$BINARY_PATH" tendermint show-node-id --home "$NODE2_HOME")" - -echo "==> Configuring node1..." -configure_node \ - "$NODE1_HOME" \ - "$NODE1_RPC_PORT" \ - "$NODE1_P2P_PORT" \ - "$NODE1_API_PORT" \ - "$NODE1_GRPC_PORT" \ - "$NODE2_ID@127.0.0.1:$NODE2_P2P_PORT" \ - "$NODE1_MINA_PRIV_KEY" - -echo "==> Configuring node2..." -configure_node \ - "$NODE2_HOME" \ - "$NODE2_RPC_PORT" \ - "$NODE2_P2P_PORT" \ - "$NODE2_API_PORT" \ - "$NODE2_GRPC_PORT" \ - "$NODE1_ID@127.0.0.1:$NODE1_P2P_PORT" \ - "$NODE2_MINA_PRIV_KEY" +"$BINARY_PATH" genesis validate-genesis --home "$PRIMARY_HOME" >/dev/null 2>&1 + +for ((i = PRIMARY_NODE_INDEX + 1; i <= VALIDATOR_COUNT; i++)); do + echo "==> Copying final genesis to ${NODE_MONIKERS[i]}..." + cp "$PRIMARY_GENESIS_FILE" "${NODE_GENESIS_FILES[i]}" +done + +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + NODE_IDS[i]="$("$BINARY_PATH" tendermint show-node-id --home "${NODE_HOMES[i]}")" +done + +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + echo "==> Configuring ${NODE_MONIKERS[i]}..." + configure_node \ + "${NODE_HOMES[i]}" \ + "${NODE_RPC_PORTS[i]}" \ + "${NODE_P2P_PORTS[i]}" \ + "${NODE_API_PORTS[i]}" \ + "${NODE_GRPC_PORTS[i]}" \ + "$(build_persistent_peers "$i")" \ + "${NODE_MINA_PRIV_KEYS[i]}" +done echo "" echo "Setup complete." +echo " validators: $VALIDATOR_COUNT" echo " binary: $BINARY_PATH" echo " compat binary: $COMPAT_BINARY_PATH" -echo " node1 home: $NODE1_HOME" -echo " node2 home: $NODE2_HOME" -echo " node1 address: $NODE1_ADDR" -echo " node2 address: $NODE2_ADDR" -echo " node1 cosmos key: $NODE1_COSMOS_PUB_KEY" -echo " node2 cosmos key: $NODE2_COSMOS_PUB_KEY" -echo " node1 mina key: $NODE1_MINA_PUB_KEY" -echo " node2 mina key: $NODE2_MINA_PUB_KEY" +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + echo " ${NODE_MONIKERS[i]} home: ${NODE_HOMES[i]}" + echo " ${NODE_MONIKERS[i]} address: ${NODE_ADDRS[i]}" + echo " ${NODE_MONIKERS[i]} cosmos key: ${NODE_COSMOS_PUB_KEYS[i]}" + echo " ${NODE_MONIKERS[i]} mina key: ${NODE_MINA_PUB_KEYS[i]}" +done echo "" echo "Start the nodes in separate terminals:" -echo " $BINARY_PATH start --home $NODE1_HOME" -echo " $BINARY_PATH start --home $NODE2_HOME" +for ((i = 1; i <= VALIDATOR_COUNT; i++)); do + echo " $BINARY_PATH start --home ${NODE_HOMES[i]}" +done echo "" echo "Validation examples:" -echo " curl -s http://localhost:$NODE1_RPC_PORT/validators | python3 -m json.tool | grep total" -echo " $BINARY_PATH query votepersistence vote-ext-body-by-height 5 --home $NODE1_HOME" +echo " curl -s http://localhost:${NODE_RPC_PORTS[PRIMARY_NODE_INDEX]}/validators | python3 -m json.tool | grep total" +echo " $BINARY_PATH query votepersistence vote-ext-body-by-height 5 --home $PRIMARY_HOME" diff --git a/scripts/setup_local_testnet_helper.py b/scripts/setup_local_testnet_helper.py index a84917d1..69166dbd 100644 --- a/scripts/setup_local_testnet_helper.py +++ b/scripts/setup_local_testnet_helper.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 import argparse +import base64 +import hashlib import json import re import sys @@ -8,6 +10,11 @@ from typing import Optional +MINA_SCALAR_FIELD = int( + "40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", 16 +) + + def read_text(path_str: str) -> str: return Path(path_str).read_text(encoding="utf-8") @@ -49,6 +56,40 @@ def read_consensus_pub_key(priv_validator_key_path: str) -> int: return 0 +def generate_default_mina_priv_key(index: str) -> int: + data = hashlib.sha256(f"pulsar-local-testnet-node-{index}".encode()).digest() + + while True: + value = int.from_bytes(data, "big") % MINA_SCALAR_FIELD + if value != 0: + print(base64.b64encode(value.to_bytes(32, "big")).decode()) + return 0 + + data = hashlib.sha256(data).digest() + + +def validate_mina_priv_key(index: str, mina_priv_key: str) -> int: + try: + raw = base64.b64decode(mina_priv_key, validate=True) + except Exception as exc: + raise SystemExit(f"node{index} mina private key is not valid base64: {exc}") + + if len(raw) != 32: + raise SystemExit( + f"node{index} mina private key must decode to 32 bytes, got {len(raw)}" + ) + + value = int.from_bytes(raw, "big") + if value == 0 or value >= MINA_SCALAR_FIELD: + raise SystemExit( + "node" + f"{index} mina private key must represent a non-zero scalar smaller than " + f"{MINA_SCALAR_FIELD:x}" + ) + + return 0 + + def extract_gentx_consensus_pub_keys(genesis) -> list[str]: gentxs = genesis["app_state"]["genutil"]["gen_txs"] cosmos_keys = [] @@ -136,6 +177,13 @@ def build_parser() -> argparse.ArgumentParser: set_height.add_argument("--genesis", required=True) set_height.add_argument("--height", required=True) + generate_mina_key = subparsers.add_parser("generate-default-mina-priv-key") + generate_mina_key.add_argument("--index", required=True) + + validate_mina_key = subparsers.add_parser("validate-mina-priv-key") + validate_mina_key.add_argument("--index", required=True) + validate_mina_key.add_argument("--mina-priv-key", required=True) + patch_registry = subparsers.add_parser("patch-keyregistry") patch_registry.add_argument("--genesis", required=True) patch_registry.add_argument("--cosmos-key", action="append") @@ -159,6 +207,10 @@ def main() -> int: return read_consensus_pub_key(args.priv_validator_key) if args.command == "set-vote-extension-height": return set_vote_extension_height(args.genesis, args.height) + if args.command == "generate-default-mina-priv-key": + return generate_default_mina_priv_key(args.index) + if args.command == "validate-mina-priv-key": + return validate_mina_priv_key(args.index, args.mina_priv_key) if args.command == "patch-keyregistry": return patch_keyregistry(args.genesis, args.mina_pub_key, args.cosmos_key) if args.command == "update-app-config": From 23ebad12bc0ff60c9f7f78bd1dc3299fce65c8af Mon Sep 17 00:00:00 2001 From: Yusuf Date: Thu, 7 May 2026 16:26:41 +0300 Subject: [PATCH 46/63] fix: solve the repeated entry problem --- abci/helpers.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/abci/helpers.go b/abci/helpers.go index cd946c87..bca4d0b7 100644 --- a/abci/helpers.go +++ b/abci/helpers.go @@ -209,6 +209,7 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl abc var currentValidatorStakePower int64 valInfoMap := make(map[string]stakingTypes.ValidatorI) + validatorSeen := make(map[string]bool) currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) if err != nil { @@ -244,6 +245,12 @@ func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl abc return false, err } + if validatorSeen[vote.ConsensusPublicKey] { + continue + } + + validatorSeen[vote.ConsensusPublicKey] = true + exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, pk) if err != nil { return false, err From f924d691e6472939debf1d582e2f6e4736ad077e Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 8 May 2026 19:26:19 +0300 Subject: [PATCH 47/63] feat: initialize bridge module --- api/pulsarchain/abci/payload.pb.go | 3 +- app/app.go | 5 +- app/app_config.go | 9 + buf.lock | 4 +- docs/static/openapi.json | 2 +- go.mod | 2 +- .../pulsarchain/bridge/module/v1/module.proto | 15 + proto/pulsarchain/bridge/v1/genesis.proto | 17 + proto/pulsarchain/bridge/v1/params.proto | 13 + proto/pulsarchain/bridge/v1/query.proto | 30 + proto/pulsarchain/bridge/v1/tx.proto | 40 ++ proto/pulsarchain/keyregistry/v1/tx.proto | 2 +- .../votepersistence/v1/query.proto | 2 - x/bridge/keeper/genesis.go | 25 + x/bridge/keeper/genesis_test.go | 24 + x/bridge/keeper/keeper.go | 60 ++ x/bridge/keeper/keeper_test.go | 56 ++ x/bridge/keeper/msg_server.go | 17 + x/bridge/keeper/msg_update_params.go | 32 + x/bridge/keeper/msg_update_params_test.go | 68 ++ x/bridge/keeper/query.go | 17 + x/bridge/keeper/query_params.go | 26 + x/bridge/keeper/query_params_test.go | 22 + x/bridge/module/autocli.go | 35 + x/bridge/module/depinject.go | 62 ++ x/bridge/module/module.go | 143 +++++ x/bridge/module/simulation.go | 34 + x/bridge/types/codec.go | 14 + x/bridge/types/errors.go | 12 + x/bridge/types/expected_keepers.go | 27 + x/bridge/types/genesis.go | 14 + x/bridge/types/genesis.pb.go | 327 ++++++++++ x/bridge/types/genesis_test.go | 37 ++ x/bridge/types/keys.go | 19 + x/bridge/types/module.pb.go | 325 ++++++++++ x/bridge/types/params.go | 17 + x/bridge/types/params.pb.go | 292 +++++++++ x/bridge/types/query.pb.go | 542 ++++++++++++++++ x/bridge/types/query.pb.gw.go | 153 +++++ x/bridge/types/tx.pb.go | 601 ++++++++++++++++++ x/bridge/types/types.go | 1 + x/keyregistry/types/genesis.pb.go | 7 +- x/keyregistry/types/key_update_type.pb.go | 3 +- x/keyregistry/types/module.pb.go | 5 +- x/keyregistry/types/params.pb.go | 7 +- x/keyregistry/types/public_key_pair.pb.go | 3 +- x/keyregistry/types/query.pb.go | 7 +- x/keyregistry/types/tx.pb.go | 7 +- x/pulsar/types/genesis.pb.go | 7 +- x/pulsar/types/module.pb.go | 5 +- x/pulsar/types/params.pb.go | 7 +- x/pulsar/types/query.pb.go | 7 +- x/pulsar/types/tx.pb.go | 7 +- x/votepersistence/types/genesis.pb.go | 7 +- x/votepersistence/types/module.pb.go | 5 +- x/votepersistence/types/params.pb.go | 7 +- x/votepersistence/types/query.pb.go | 7 +- x/votepersistence/types/tx.pb.go | 7 +- x/votepersistence/types/vote_ext_body.pb.go | 3 +- 59 files changed, 3200 insertions(+), 54 deletions(-) create mode 100644 proto/pulsarchain/bridge/module/v1/module.proto create mode 100644 proto/pulsarchain/bridge/v1/genesis.proto create mode 100644 proto/pulsarchain/bridge/v1/params.proto create mode 100644 proto/pulsarchain/bridge/v1/query.proto create mode 100644 proto/pulsarchain/bridge/v1/tx.proto create mode 100644 x/bridge/keeper/genesis.go create mode 100644 x/bridge/keeper/genesis_test.go create mode 100644 x/bridge/keeper/keeper.go create mode 100644 x/bridge/keeper/keeper_test.go create mode 100644 x/bridge/keeper/msg_server.go create mode 100644 x/bridge/keeper/msg_update_params.go create mode 100644 x/bridge/keeper/msg_update_params_test.go create mode 100644 x/bridge/keeper/query.go create mode 100644 x/bridge/keeper/query_params.go create mode 100644 x/bridge/keeper/query_params_test.go create mode 100644 x/bridge/module/autocli.go create mode 100644 x/bridge/module/depinject.go create mode 100644 x/bridge/module/module.go create mode 100644 x/bridge/module/simulation.go create mode 100644 x/bridge/types/codec.go create mode 100644 x/bridge/types/errors.go create mode 100644 x/bridge/types/expected_keepers.go create mode 100644 x/bridge/types/genesis.go create mode 100644 x/bridge/types/genesis.pb.go create mode 100644 x/bridge/types/genesis_test.go create mode 100644 x/bridge/types/keys.go create mode 100644 x/bridge/types/module.pb.go create mode 100644 x/bridge/types/params.go create mode 100644 x/bridge/types/params.pb.go create mode 100644 x/bridge/types/query.pb.go create mode 100644 x/bridge/types/query.pb.gw.go create mode 100644 x/bridge/types/tx.pb.go create mode 100644 x/bridge/types/types.go diff --git a/api/pulsarchain/abci/payload.pb.go b/api/pulsarchain/abci/payload.pb.go index 6adc1b07..f67e0ada 100644 --- a/api/pulsarchain/abci/payload.pb.go +++ b/api/pulsarchain/abci/payload.pb.go @@ -5,10 +5,11 @@ package abcipb import ( fmt "fmt" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/app/app.go b/app/app.go index 122cbc6f..491b5dd1 100644 --- a/app/app.go +++ b/app/app.go @@ -51,6 +51,7 @@ import ( "github.com/node101-io/mina-signer-go/keys" vote_ext "github.com/node101-io/pulsar-chain/abci" "github.com/node101-io/pulsar-chain/docs" + bridgemodulekeeper "github.com/node101-io/pulsar-chain/x/bridge/keeper" keyregistrymodulekeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" pulsarmodulekeeper "github.com/node101-io/pulsar-chain/x/pulsar/keeper" votepersistencemodulekeeper "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" @@ -111,7 +112,8 @@ type App struct { KeyregistryKeeper keyregistrymodulekeeper.Keeper VotepersistenceKeeper votepersistencemodulekeeper.Keeper - AbciHandler *vote_ext.AbciHandler + AbciHandler *vote_ext.AbciHandler + BridgeKeeper bridgemodulekeeper.Keeper } func init() { @@ -194,6 +196,7 @@ func New( &app.PulsarKeeper, &app.KeyregistryKeeper, &app.VotepersistenceKeeper, + &app.BridgeKeeper, ); err != nil { panic(err) } diff --git a/app/app_config.go b/app/app_config.go index dc747fa5..930f0af7 100644 --- a/app/app_config.go +++ b/app/app_config.go @@ -3,6 +3,8 @@ package app import ( "time" + _ "github.com/node101-io/pulsar-chain/x/bridge/module" + bridgemoduletypes "github.com/node101-io/pulsar-chain/x/bridge/types" _ "github.com/node101-io/pulsar-chain/x/keyregistry/module" keyregistrymoduletypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" _ "github.com/node101-io/pulsar-chain/x/pulsar/module" @@ -133,6 +135,7 @@ var ( pulsarmoduletypes.ModuleName, keyregistrymoduletypes.ModuleName, votepersistencemoduletypes.ModuleName, + bridgemoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/beginBlockers }, EndBlockers: []string{ @@ -144,6 +147,7 @@ var ( pulsarmoduletypes.ModuleName, keyregistrymoduletypes.ModuleName, votepersistencemoduletypes.ModuleName, + bridgemoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/endBlockers }, // The following is mostly only needed when ModuleName != StoreKey name. @@ -183,6 +187,7 @@ var ( pulsarmoduletypes.ModuleName, keyregistrymoduletypes.ModuleName, votepersistencemoduletypes.ModuleName, + bridgemoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/initGenesis }, }), @@ -291,6 +296,10 @@ var ( Name: votepersistencemoduletypes.ModuleName, Config: appconfig.WrapAny(&votepersistencemoduletypes.Module{}), }, + { + Name: bridgemoduletypes.ModuleName, + Config: appconfig.WrapAny(&bridgemoduletypes.Module{}), + }, // this line is used by starport scaffolding # stargate/app/moduleConfig }, }) diff --git a/buf.lock b/buf.lock index 2da6522e..fd28dbd0 100644 --- a/buf.lock +++ b/buf.lock @@ -17,8 +17,8 @@ deps: commit: dc427cb4519143d8996361c045a29ad7 digest: b5:8693e72e230bfaf58a88a47a4093ba99f6252c1957a45582567959b38a8563e2abd11443372283d75f4f2306a7e3cc9bf63604d284a016c11966fca4b74b7a28 - name: buf.build/googleapis/googleapis - commit: 536964a08a534d51b8f30f2d6751f1f9 - digest: b5:3e05d27e797b00c345fadd3c15cf0e16c4cc693036a55059721e66d6ce22a96264a4897658c9243bb0874fa9ca96e437589eb512189d2754604a626c632f6030 + commit: c17df5b2beca46928cc87d5656bd5343 + digest: b5:648a01e0170d4512dea7d564016165decd1ed6e34bef79fe54753e51ad7e27545709ad9157d7551270147d551155c595a2fb0bf5bb33b1c83040ddbce915c604 - name: buf.build/protocolbuffers/wellknowntypes commit: 9d16d599a978406980f6e2f081331a93 digest: b5:dd06e497a5c52f5ddf6ec02b3c7d289cc6c0432093fc2f6bf7a4fb5fae786c3e4c893e55d2759ffb6833268daf3de0bce303a406fed15725790528f2c27dc219 diff --git a/docs/static/openapi.json b/docs/static/openapi.json index fe534475..9446f18c 100644 --- a/docs/static/openapi.json +++ b/docs/static/openapi.json @@ -1 +1 @@ -{"id":"github.com/node101-io/pulsar-chain","consumes":["application/json"],"produces":["application/json"],"swagger":"2.0","info":{"description":"Chain github.com/node101-io/pulsar-chain REST API","title":"HTTP API Console","contact":{"name":"github.com/node101-io/pulsar-chain"},"version":"version not set"},"paths":{"/node101-io/pulsar-chain/keyregistry/v1/get_user_cosmos_public_key/{user_mina_public_key}":{"get":{"tags":["Query"],"summary":"GetUserCosmosPublicKey Queries a list of GetUserCosmosPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserCosmosPublicKey","parameters":[{"type":"string","format":"byte","name":"user_mina_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_user_mina_public_key/{user_cosmos_public_key}":{"get":{"tags":["Query"],"summary":"GetUserMinaPublicKey Queries a list of GetUserMinaPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserMinaPublicKey","parameters":[{"type":"string","format":"byte","name":"user_cosmos_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_cosmos_pub_key/{validator_mina_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorCosmosPubKey Queries a list of GetValidatorCosmosPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorCosmosPubKey","parameters":[{"type":"string","format":"byte","name":"validator_mina_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_mina_pub_key/{validator_cosmos_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorMinaPubKey Queries a list of GetValidatorMinaPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorMinaPubKey","parameters":[{"type":"string","format":"byte","name":"validator_cosmos_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin9","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin13","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/vote_ext_body_by_height/{block_height}":{"get":{"tags":["Query"],"summary":"VoteExtBodyByHeight Queries a list of VoteExtBodyByHeight items.","operationId":"GithubComnode101IopulsarChainQuery_VoteExtBodyByHeight","parameters":[{"type":"string","format":"int64","name":"block_height","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.VoteExtBody"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/pulsar/pulsar/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_Params","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsar.pulsar.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}}},"definitions":{"google.protobuf.Any":{"type":"object","properties":{"@type":{"type":"string"}},"additionalProperties":{}},"google.rpc.Status":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"details":{"type":"array","items":{"type":"object","$ref":"#/definitions/google.protobuf.Any"}},"message":{"type":"string"}}},"pulsar.pulsar.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsar.pulsar.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsar.pulsar.v1.Params"}}},"pulsarchain.keyregistry.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse":{"description":"QueryGetUserCosmosPublicKeyResponse defines the QueryGetUserCosmosPublicKeyResponse message.","type":"object","properties":{"user_cosmos_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse":{"description":"QueryGetUserMinaPublicKeyResponse defines the QueryGetUserMinaPublicKeyResponse message.","type":"object","properties":{"user_mina_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse":{"description":"QueryGetValidatorCosmosPubKeyResponse defines the QueryGetValidatorCosmosPubKeyResponse message.","type":"object","properties":{"validator_cosmos_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse":{"description":"QueryGetValidatorMinaPubKeyResponse defines the QueryGetValidatorMinaPubKeyResponse message.","type":"object","properties":{"validator_mina_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.keyregistry.v1.Params"}}},"pulsarchain.votepersistence.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.votepersistence.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.votepersistence.v1.Params"}}},"pulsarchain.votepersistence.v1.VoteExtBody":{"description":"VoteExtBody defines the VoteExtBody message.","type":"object","properties":{"actions_reduced_root":{"type":"string"},"current_block_height":{"type":"string","format":"int64"},"current_state_root":{"type":"string","format":"byte"},"next_validator_set_hash":{"type":"string","format":"byte"}}}},"tags":[{"name":"Query"},{"name":"Msg"}]} \ No newline at end of file +{"id":"github.com/node101-io/pulsar-chain","consumes":["application/json"],"produces":["application/json"],"swagger":"2.0","info":{"description":"Chain github.com/node101-io/pulsar-chain REST API","title":"HTTP API Console","contact":{"name":"github.com/node101-io/pulsar-chain"},"version":"version not set"},"paths":{"/node101-io/pulsar-chain/bridge/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin7","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.bridge.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_user_cosmos_public_key/{user_mina_public_key}":{"get":{"tags":["Query"],"summary":"GetUserCosmosPublicKey Queries a list of GetUserCosmosPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserCosmosPublicKey","parameters":[{"type":"string","format":"byte","name":"user_mina_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_user_mina_public_key/{user_cosmos_public_key}":{"get":{"tags":["Query"],"summary":"GetUserMinaPublicKey Queries a list of GetUserMinaPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserMinaPublicKey","parameters":[{"type":"string","format":"byte","name":"user_cosmos_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_cosmos_pub_key/{validator_mina_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorCosmosPubKey Queries a list of GetValidatorCosmosPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorCosmosPubKey","parameters":[{"type":"string","format":"byte","name":"validator_mina_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_mina_pub_key/{validator_cosmos_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorMinaPubKey Queries a list of GetValidatorMinaPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorMinaPubKey","parameters":[{"type":"string","format":"byte","name":"validator_cosmos_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin13","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin17","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/vote_ext_body_by_height/{block_height}":{"get":{"tags":["Query"],"summary":"VoteExtBodyByHeight Queries a list of VoteExtBodyByHeight items.","operationId":"GithubComnode101IopulsarChainQuery_VoteExtBodyByHeight","parameters":[{"type":"string","format":"int64","name":"block_height","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.VoteExtBody"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/pulsar/pulsar/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_Params","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsar.pulsar.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}}},"definitions":{"google.protobuf.Any":{"type":"object","properties":{"@type":{"type":"string"}},"additionalProperties":{}},"google.rpc.Status":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"details":{"type":"array","items":{"type":"object","$ref":"#/definitions/google.protobuf.Any"}},"message":{"type":"string"}}},"pulsar.pulsar.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsar.pulsar.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsar.pulsar.v1.Params"}}},"pulsarchain.bridge.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.bridge.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.bridge.v1.Params"}}},"pulsarchain.keyregistry.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse":{"description":"QueryGetUserCosmosPublicKeyResponse defines the QueryGetUserCosmosPublicKeyResponse message.","type":"object","properties":{"user_cosmos_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse":{"description":"QueryGetUserMinaPublicKeyResponse defines the QueryGetUserMinaPublicKeyResponse message.","type":"object","properties":{"user_mina_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse":{"description":"QueryGetValidatorCosmosPubKeyResponse defines the QueryGetValidatorCosmosPubKeyResponse message.","type":"object","properties":{"validator_cosmos_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse":{"description":"QueryGetValidatorMinaPubKeyResponse defines the QueryGetValidatorMinaPubKeyResponse message.","type":"object","properties":{"validator_mina_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.keyregistry.v1.Params"}}},"pulsarchain.votepersistence.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.votepersistence.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.votepersistence.v1.Params"}}},"pulsarchain.votepersistence.v1.VoteExtBody":{"description":"VoteExtBody defines the VoteExtBody message.","type":"object","properties":{"actions_reduced_root":{"type":"string"},"current_block_height":{"type":"string","format":"int64"},"current_state_root":{"type":"string","format":"byte"},"next_validator_set_hash":{"type":"string","format":"byte"}}}},"tags":[{"name":"Query"},{"name":"Msg"}]} \ No newline at end of file diff --git a/go.mod b/go.mod index 780ad485..7f628ea5 100644 --- a/go.mod +++ b/go.mod @@ -44,6 +44,7 @@ require ( github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 + go.uber.org/mock v0.6.0 google.golang.org/genproto/googleapis/api v0.0.0-20260217215200-42d3e9bedb6d google.golang.org/grpc v1.79.1 google.golang.org/protobuf v1.36.11 @@ -404,7 +405,6 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect go.opentelemetry.io/otel/trace v1.40.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - go.uber.org/mock v0.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.1 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect diff --git a/proto/pulsarchain/bridge/module/v1/module.proto b/proto/pulsarchain/bridge/module/v1/module.proto new file mode 100644 index 00000000..814a8911 --- /dev/null +++ b/proto/pulsarchain/bridge/module/v1/module.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; +package pulsarchain.bridge.module.v1; + +import "cosmos/app/v1alpha1/module.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/bridge/types"; + +// Module is the config object for the module. +message Module { + option (cosmos.app.v1alpha1.module) = {go_import: "github.com/node101-io/pulsar-chain/x/bridge"}; + + // authority defines the custom module authority. + // If not set, defaults to the governance module. + string authority = 1; +} diff --git a/proto/pulsarchain/bridge/v1/genesis.proto b/proto/pulsarchain/bridge/v1/genesis.proto new file mode 100644 index 00000000..1b8f02e3 --- /dev/null +++ b/proto/pulsarchain/bridge/v1/genesis.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package pulsarchain.bridge.v1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; +import "pulsarchain/bridge/v1/params.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/bridge/types"; + +// GenesisState defines the bridge module's genesis state. +message GenesisState { + // params defines all the parameters of the module. + Params params = 1 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} diff --git a/proto/pulsarchain/bridge/v1/params.proto b/proto/pulsarchain/bridge/v1/params.proto new file mode 100644 index 00000000..98bbe2b4 --- /dev/null +++ b/proto/pulsarchain/bridge/v1/params.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package pulsarchain.bridge.v1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/bridge/types"; + +// Params defines the parameters for the module. +message Params { + option (amino.name) = "pulsarchain/x/bridge/Params"; + option (gogoproto.equal) = true; +} diff --git a/proto/pulsarchain/bridge/v1/query.proto b/proto/pulsarchain/bridge/v1/query.proto new file mode 100644 index 00000000..e71680ad --- /dev/null +++ b/proto/pulsarchain/bridge/v1/query.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; +package pulsarchain.bridge.v1; + +import "amino/amino.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "pulsarchain/bridge/v1/params.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/bridge/types"; + +// Query defines the gRPC querier service. +service Query { + // Parameters queries the parameters of the module. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/node101-io/pulsar-chain/bridge/v1/params"; + } +} + +// QueryParamsRequest is request type for the Query/Params RPC method. +message QueryParamsRequest {} + +// QueryParamsResponse is response type for the Query/Params RPC method. +message QueryParamsResponse { + // params holds all the parameters of this module. + Params params = 1 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} diff --git a/proto/pulsarchain/bridge/v1/tx.proto b/proto/pulsarchain/bridge/v1/tx.proto new file mode 100644 index 00000000..45d49ad0 --- /dev/null +++ b/proto/pulsarchain/bridge/v1/tx.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package pulsarchain.bridge.v1; + +import "amino/amino.proto"; +import "cosmos/msg/v1/msg.proto"; +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "pulsarchain/bridge/v1/params.proto"; + +option go_package = "github.com/node101-io/pulsar-chain/x/bridge/types"; + +// Msg defines the Msg service. +service Msg { + option (cosmos.msg.v1.service) = true; + + // UpdateParams defines a (governance) operation for updating the module + // parameters. The authority defaults to the x/gov module account. + rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); +} + +// MsgUpdateParams is the Msg/UpdateParams request type. +message MsgUpdateParams { + option (cosmos.msg.v1.signer) = "authority"; + option (amino.name) = "pulsarchain/x/bridge/MsgUpdateParams"; + + // authority is the address that controls the module (defaults to x/gov unless overwritten). + string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // params defines the module parameters to update. + // + // NOTE: All parameters must be supplied. + Params params = 2 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} + +// MsgUpdateParamsResponse defines the response structure for executing a +// MsgUpdateParams message. +message MsgUpdateParamsResponse {} diff --git a/proto/pulsarchain/keyregistry/v1/tx.proto b/proto/pulsarchain/keyregistry/v1/tx.proto index 3c8a4dae..324f8f08 100644 --- a/proto/pulsarchain/keyregistry/v1/tx.proto +++ b/proto/pulsarchain/keyregistry/v1/tx.proto @@ -6,8 +6,8 @@ import "amino/amino.proto"; import "cosmos/msg/v1/msg.proto"; import "cosmos_proto/cosmos.proto"; import "gogoproto/gogo.proto"; -import "pulsarchain/keyregistry/v1/params.proto"; import "pulsarchain/keyregistry/v1/key_update_type.proto"; +import "pulsarchain/keyregistry/v1/params.proto"; option go_package = "github.com/node101-io/pulsar-chain/x/keyregistry/types"; diff --git a/proto/pulsarchain/votepersistence/v1/query.proto b/proto/pulsarchain/votepersistence/v1/query.proto index 215bd80d..2d66b251 100644 --- a/proto/pulsarchain/votepersistence/v1/query.proto +++ b/proto/pulsarchain/votepersistence/v1/query.proto @@ -9,7 +9,6 @@ import "google/api/annotations.proto"; import "pulsarchain/votepersistence/v1/params.proto"; import "pulsarchain/votepersistence/v1/vote_ext_body.proto"; - option go_package = "github.com/node101-io/pulsar-chain/x/votepersistence/types"; // Query defines the gRPC querier service. @@ -41,4 +40,3 @@ message QueryParamsResponse { message QueryVoteExtBodyByHeightRequest { int64 block_height = 1; } - diff --git a/x/bridge/keeper/genesis.go b/x/bridge/keeper/genesis.go new file mode 100644 index 00000000..95689ace --- /dev/null +++ b/x/bridge/keeper/genesis.go @@ -0,0 +1,25 @@ +package keeper + +import ( + "context" + + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +// InitGenesis initializes the module's state from a provided genesis state. +func (k Keeper) InitGenesis(ctx context.Context, genState types.GenesisState) error { + return k.Params.Set(ctx, genState.Params) +} + +// ExportGenesis returns the module's exported genesis. +func (k Keeper) ExportGenesis(ctx context.Context) (*types.GenesisState, error) { + var err error + + genesis := types.DefaultGenesis() + genesis.Params, err = k.Params.Get(ctx) + if err != nil { + return nil, err + } + + return genesis, nil +} diff --git a/x/bridge/keeper/genesis_test.go b/x/bridge/keeper/genesis_test.go new file mode 100644 index 00000000..12fb068c --- /dev/null +++ b/x/bridge/keeper/genesis_test.go @@ -0,0 +1,24 @@ +package keeper_test + +import ( + "testing" + + "github.com/node101-io/pulsar-chain/x/bridge/types" + + "github.com/stretchr/testify/require" +) + +func TestGenesis(t *testing.T) { + genesisState := types.GenesisState{ + Params: types.DefaultParams(), + } + + f := initFixture(t) + err := f.keeper.InitGenesis(f.ctx, genesisState) + require.NoError(t, err) + got, err := f.keeper.ExportGenesis(f.ctx) + require.NoError(t, err) + require.NotNil(t, got) + + require.EqualExportedValues(t, genesisState.Params, got.Params) +} diff --git a/x/bridge/keeper/keeper.go b/x/bridge/keeper/keeper.go new file mode 100644 index 00000000..6e318cca --- /dev/null +++ b/x/bridge/keeper/keeper.go @@ -0,0 +1,60 @@ +package keeper + +import ( + "fmt" + + "cosmossdk.io/collections" + "cosmossdk.io/core/address" + corestore "cosmossdk.io/core/store" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +type Keeper struct { + storeService corestore.KVStoreService + cdc codec.Codec + addressCodec address.Codec + // Address capable of executing a MsgUpdateParams message. + // Typically, this should be the x/gov module account. + authority []byte + + Schema collections.Schema + Params collections.Item[types.Params] +} + +func NewKeeper( + storeService corestore.KVStoreService, + cdc codec.Codec, + addressCodec address.Codec, + authority []byte, + +) Keeper { + if _, err := addressCodec.BytesToString(authority); err != nil { + panic(fmt.Sprintf("invalid authority address %s: %s", authority, err)) + } + + sb := collections.NewSchemaBuilder(storeService) + + k := Keeper{ + storeService: storeService, + cdc: cdc, + addressCodec: addressCodec, + authority: authority, + + Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), + } + + schema, err := sb.Build() + if err != nil { + panic(err) + } + k.Schema = schema + + return k +} + +// GetAuthority returns the module's authority. +func (k Keeper) GetAuthority() []byte { + return k.authority +} diff --git a/x/bridge/keeper/keeper_test.go b/x/bridge/keeper/keeper_test.go new file mode 100644 index 00000000..a0ace733 --- /dev/null +++ b/x/bridge/keeper/keeper_test.go @@ -0,0 +1,56 @@ +package keeper_test + +import ( + "context" + "testing" + + "cosmossdk.io/core/address" + storetypes "cosmossdk.io/store/types" + addresscodec "github.com/cosmos/cosmos-sdk/codec/address" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/node101-io/pulsar-chain/x/bridge/keeper" + module "github.com/node101-io/pulsar-chain/x/bridge/module" + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +type fixture struct { + ctx context.Context + keeper keeper.Keeper + addressCodec address.Codec +} + +func initFixture(t *testing.T) *fixture { + t.Helper() + + encCfg := moduletestutil.MakeTestEncodingConfig(module.AppModule{}) + addressCodec := addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + storeKey := storetypes.NewKVStoreKey(types.StoreKey) + + storeService := runtime.NewKVStoreService(storeKey) + ctx := testutil.DefaultContextWithDB(t, storeKey, storetypes.NewTransientStoreKey("transient_test")).Ctx + + authority := authtypes.NewModuleAddress(types.GovModuleName) + + k := keeper.NewKeeper( + storeService, + encCfg.Codec, + addressCodec, + authority, + ) + + // Initialize params + if err := k.Params.Set(ctx, types.DefaultParams()); err != nil { + t.Fatalf("failed to set params: %v", err) + } + + return &fixture{ + ctx: ctx, + keeper: k, + addressCodec: addressCodec, + } +} diff --git a/x/bridge/keeper/msg_server.go b/x/bridge/keeper/msg_server.go new file mode 100644 index 00000000..a6f825f3 --- /dev/null +++ b/x/bridge/keeper/msg_server.go @@ -0,0 +1,17 @@ +package keeper + +import ( + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{Keeper: keeper} +} + +var _ types.MsgServer = msgServer{} diff --git a/x/bridge/keeper/msg_update_params.go b/x/bridge/keeper/msg_update_params.go new file mode 100644 index 00000000..726ba745 --- /dev/null +++ b/x/bridge/keeper/msg_update_params.go @@ -0,0 +1,32 @@ +package keeper + +import ( + "bytes" + "context" + + errorsmod "cosmossdk.io/errors" + + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +func (k msgServer) UpdateParams(ctx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { + authority, err := k.addressCodec.StringToBytes(req.Authority) + if err != nil { + return nil, errorsmod.Wrap(err, "invalid authority address") + } + + if !bytes.Equal(k.GetAuthority(), authority) { + expectedAuthorityStr, _ := k.addressCodec.BytesToString(k.GetAuthority()) + return nil, errorsmod.Wrapf(types.ErrInvalidSigner, "invalid authority; expected %s, got %s", expectedAuthorityStr, req.Authority) + } + + if err := req.Params.Validate(); err != nil { + return nil, err + } + + if err := k.Params.Set(ctx, req.Params); err != nil { + return nil, err + } + + return &types.MsgUpdateParamsResponse{}, nil +} diff --git a/x/bridge/keeper/msg_update_params_test.go b/x/bridge/keeper/msg_update_params_test.go new file mode 100644 index 00000000..ff12b03f --- /dev/null +++ b/x/bridge/keeper/msg_update_params_test.go @@ -0,0 +1,68 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/node101-io/pulsar-chain/x/bridge/keeper" + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +func TestMsgUpdateParams(t *testing.T) { + f := initFixture(t) + ms := keeper.NewMsgServerImpl(f.keeper) + + params := types.DefaultParams() + require.NoError(t, f.keeper.Params.Set(f.ctx, params)) + + authorityStr, err := f.addressCodec.BytesToString(f.keeper.GetAuthority()) + require.NoError(t, err) + + // default params + testCases := []struct { + name string + input *types.MsgUpdateParams + expErr bool + expErrMsg string + }{ + { + name: "invalid authority", + input: &types.MsgUpdateParams{ + Authority: "invalid", + Params: params, + }, + expErr: true, + expErrMsg: "invalid authority", + }, + { + name: "send enabled param", + input: &types.MsgUpdateParams{ + Authority: authorityStr, + Params: types.Params{}, + }, + expErr: false, + }, + { + name: "all good", + input: &types.MsgUpdateParams{ + Authority: authorityStr, + Params: params, + }, + expErr: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + _, err := ms.UpdateParams(f.ctx, tc.input) + + if tc.expErr { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErrMsg) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/bridge/keeper/query.go b/x/bridge/keeper/query.go new file mode 100644 index 00000000..69201248 --- /dev/null +++ b/x/bridge/keeper/query.go @@ -0,0 +1,17 @@ +package keeper + +import ( + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +var _ types.QueryServer = queryServer{} + +// NewQueryServerImpl returns an implementation of the QueryServer interface +// for the provided Keeper. +func NewQueryServerImpl(k Keeper) types.QueryServer { + return queryServer{k} +} + +type queryServer struct { + k Keeper +} diff --git a/x/bridge/keeper/query_params.go b/x/bridge/keeper/query_params.go new file mode 100644 index 00000000..a7e1a382 --- /dev/null +++ b/x/bridge/keeper/query_params.go @@ -0,0 +1,26 @@ +package keeper + +import ( + "context" + "errors" + + "cosmossdk.io/collections" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +func (q queryServer) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + params, err := q.k.Params.Get(ctx) + if err != nil && !errors.Is(err, collections.ErrNotFound) { + return nil, status.Error(codes.Internal, "internal error") + } + + return &types.QueryParamsResponse{Params: params}, nil +} diff --git a/x/bridge/keeper/query_params_test.go b/x/bridge/keeper/query_params_test.go new file mode 100644 index 00000000..a02909dc --- /dev/null +++ b/x/bridge/keeper/query_params_test.go @@ -0,0 +1,22 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/node101-io/pulsar-chain/x/bridge/keeper" + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +func TestParamsQuery(t *testing.T) { + f := initFixture(t) + + qs := keeper.NewQueryServerImpl(f.keeper) + params := types.DefaultParams() + require.NoError(t, f.keeper.Params.Set(f.ctx, params)) + + response, err := qs.Params(f.ctx, &types.QueryParamsRequest{}) + require.NoError(t, err) + require.Equal(t, &types.QueryParamsResponse{Params: params}, response) +} diff --git a/x/bridge/module/autocli.go b/x/bridge/module/autocli.go new file mode 100644 index 00000000..91a2868c --- /dev/null +++ b/x/bridge/module/autocli.go @@ -0,0 +1,35 @@ +package bridge + +import ( + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. +func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { + return &autocliv1.ModuleOptions{ + Query: &autocliv1.ServiceCommandDescriptor{ + Service: types.Query_serviceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Params", + Use: "params", + Short: "Shows the parameters of the module", + }, + // this line is used by ignite scaffolding # autocli/query + }, + }, + Tx: &autocliv1.ServiceCommandDescriptor{ + Service: types.Msg_serviceDesc.ServiceName, + EnhanceCustomCommand: true, // only required if you want to use the custom command + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "UpdateParams", + Skip: true, // skipped because authority gated + }, + // this line is used by ignite scaffolding # autocli/tx + }, + }, + } +} diff --git a/x/bridge/module/depinject.go b/x/bridge/module/depinject.go new file mode 100644 index 00000000..4b12ff91 --- /dev/null +++ b/x/bridge/module/depinject.go @@ -0,0 +1,62 @@ +package bridge + +import ( + "cosmossdk.io/core/address" + "cosmossdk.io/core/appmodule" + "cosmossdk.io/core/store" + "cosmossdk.io/depinject" + "cosmossdk.io/depinject/appconfig" + "github.com/cosmos/cosmos-sdk/codec" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/node101-io/pulsar-chain/x/bridge/keeper" + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +var _ depinject.OnePerModuleType = AppModule{} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (AppModule) IsOnePerModuleType() {} + +func init() { + appconfig.Register( + &types.Module{}, + appconfig.Provide(ProvideModule), + ) +} + +type ModuleInputs struct { + depinject.In + + Config *types.Module + StoreService store.KVStoreService + Cdc codec.Codec + AddressCodec address.Codec + + AuthKeeper types.AuthKeeper + BankKeeper types.BankKeeper +} + +type ModuleOutputs struct { + depinject.Out + + BridgeKeeper keeper.Keeper + Module appmodule.AppModule +} + +func ProvideModule(in ModuleInputs) ModuleOutputs { + // default to governance authority if not provided + authority := authtypes.NewModuleAddress(types.GovModuleName) + if in.Config.Authority != "" { + authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) + } + k := keeper.NewKeeper( + in.StoreService, + in.Cdc, + in.AddressCodec, + authority, + ) + m := NewAppModule(in.Cdc, k, in.AuthKeeper, in.BankKeeper) + + return ModuleOutputs{BridgeKeeper: k, Module: m} +} diff --git a/x/bridge/module/module.go b/x/bridge/module/module.go new file mode 100644 index 00000000..c96abb9a --- /dev/null +++ b/x/bridge/module/module.go @@ -0,0 +1,143 @@ +package bridge + +import ( + "context" + "encoding/json" + "fmt" + + "cosmossdk.io/core/appmodule" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "google.golang.org/grpc" + + "github.com/node101-io/pulsar-chain/x/bridge/keeper" + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +var ( + _ module.AppModuleBasic = (*AppModule)(nil) + _ module.AppModule = (*AppModule)(nil) + _ module.HasGenesis = (*AppModule)(nil) + + _ appmodule.AppModule = (*AppModule)(nil) + _ appmodule.HasBeginBlocker = (*AppModule)(nil) + _ appmodule.HasEndBlocker = (*AppModule)(nil) +) + +// AppModule implements the AppModule interface that defines the inter-dependent methods that modules need to implement +type AppModule struct { + cdc codec.Codec + keeper keeper.Keeper + authKeeper types.AuthKeeper + bankKeeper types.BankKeeper +} + +func NewAppModule( + cdc codec.Codec, + keeper keeper.Keeper, + authKeeper types.AuthKeeper, + bankKeeper types.BankKeeper, +) AppModule { + return AppModule{ + cdc: cdc, + keeper: keeper, + authKeeper: authKeeper, + bankKeeper: bankKeeper, + } +} + +// IsAppModule implements the appmodule.AppModule interface. +func (AppModule) IsAppModule() {} + +// Name returns the name of the module as a string. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec registers the amino codec +func (AppModule) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module. +func (AppModule) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + if err := types.RegisterQueryHandlerClient(clientCtx.CmdContext, mux, types.NewQueryClient(clientCtx)); err != nil { + panic(err) + } +} + +// RegisterInterfaces registers a module's interface types and their concrete implementations as proto.Message. +func (AppModule) RegisterInterfaces(registrar codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registrar) +} + +// RegisterServices registers a gRPC query service to respond to the module-specific gRPC queries +func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error { + types.RegisterMsgServer(registrar, keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(registrar, keeper.NewQueryServerImpl(am.keeper)) + + return nil +} + +// DefaultGenesis returns a default GenesisState for the module, marshalled to json.RawMessage. +// The default GenesisState need to be defined by the module developer and is primarily used for testing. +func (am AppModule) DefaultGenesis(codec.JSONCodec) json.RawMessage { + return am.cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +// ValidateGenesis used to validate the GenesisState, given in its json.RawMessage form. +func (am AppModule) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { + var genState types.GenesisState + if err := am.cdc.UnmarshalJSON(bz, &genState); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + + return genState.Validate() +} + +// InitGenesis performs the module's genesis initialization. It returns no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, _ codec.JSONCodec, gs json.RawMessage) { + var genState types.GenesisState + // Initialize global index to index in genesis state + if err := am.cdc.UnmarshalJSON(gs, &genState); err != nil { + panic(fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)) + } + + if err := am.keeper.InitGenesis(ctx, genState); err != nil { + panic(fmt.Errorf("failed to initialize %s genesis state: %w", types.ModuleName, err)) + } +} + +// ExportGenesis returns the module's exported genesis state as raw JSON bytes. +func (am AppModule) ExportGenesis(ctx sdk.Context, _ codec.JSONCodec) json.RawMessage { + genState, err := am.keeper.ExportGenesis(ctx) + if err != nil { + panic(fmt.Errorf("failed to export %s genesis state: %w", types.ModuleName, err)) + } + + bz, err := am.cdc.MarshalJSON(genState) + if err != nil { + panic(fmt.Errorf("failed to marshal %s genesis state: %w", types.ModuleName, err)) + } + + return bz +} + +// ConsensusVersion is a sequence number for state-breaking change of the module. +// It should be incremented on each consensus-breaking change introduced by the module. +// To avoid wrong/empty versions, the initial version should be set to 1. +func (AppModule) ConsensusVersion() uint64 { return 1 } + +// BeginBlock contains the logic that is automatically triggered at the beginning of each block. +// The begin block implementation is optional. +func (am AppModule) BeginBlock(_ context.Context) error { + return nil +} + +// EndBlock contains the logic that is automatically triggered at the end of each block. +// The end block implementation is optional. +func (am AppModule) EndBlock(_ context.Context) error { + return nil +} diff --git a/x/bridge/module/simulation.go b/x/bridge/module/simulation.go new file mode 100644 index 00000000..343f5938 --- /dev/null +++ b/x/bridge/module/simulation.go @@ -0,0 +1,34 @@ +package bridge + +import ( + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +// GenerateGenesisState creates a randomized GenState of the module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + accs := make([]string, len(simState.Accounts)) + for i, acc := range simState.Accounts { + accs[i] = acc.Address.String() + } + bridgeGenesis := types.GenesisState{ + Params: types.DefaultParams(), + } + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&bridgeGenesis) +} + +// RegisterStoreDecoder registers a decoder. +func (am AppModule) RegisterStoreDecoder(_ simtypes.StoreDecoderRegistry) {} + +// WeightedOperations returns the all the gov module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + operations := make([]simtypes.WeightedOperation, 0) + return operations +} + +// ProposalMsgs returns msgs used for governance proposals for simulations. +func (am AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { + return []simtypes.WeightedProposalMsg{} +} diff --git a/x/bridge/types/codec.go b/x/bridge/types/codec.go new file mode 100644 index 00000000..56398f5e --- /dev/null +++ b/x/bridge/types/codec.go @@ -0,0 +1,14 @@ +package types + +import ( + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +func RegisterInterfaces(registrar codectypes.InterfaceRegistry) { + registrar.RegisterImplementations((*sdk.Msg)(nil), + &MsgUpdateParams{}, + ) + msgservice.RegisterMsgServiceDesc(registrar, &_Msg_serviceDesc) +} diff --git a/x/bridge/types/errors.go b/x/bridge/types/errors.go new file mode 100644 index 00000000..ea1915d2 --- /dev/null +++ b/x/bridge/types/errors.go @@ -0,0 +1,12 @@ +package types + +// DONTCOVER + +import ( + "cosmossdk.io/errors" +) + +// x/bridge module sentinel errors +var ( + ErrInvalidSigner = errors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") +) diff --git a/x/bridge/types/expected_keepers.go b/x/bridge/types/expected_keepers.go new file mode 100644 index 00000000..b175461c --- /dev/null +++ b/x/bridge/types/expected_keepers.go @@ -0,0 +1,27 @@ +package types + +import ( + "context" + + "cosmossdk.io/core/address" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// AuthKeeper defines the expected interface for the Auth module. +type AuthKeeper interface { + AddressCodec() address.Codec + GetAccount(context.Context, sdk.AccAddress) sdk.AccountI // only used for simulation + // Methods imported from account should be defined here +} + +// BankKeeper defines the expected interface for the Bank module. +type BankKeeper interface { + SpendableCoins(context.Context, sdk.AccAddress) sdk.Coins + // Methods imported from bank should be defined here +} + +// ParamSubspace defines the expected Subspace interface for parameters. +type ParamSubspace interface { + Get(context.Context, []byte, interface{}) + Set(context.Context, []byte, interface{}) +} diff --git a/x/bridge/types/genesis.go b/x/bridge/types/genesis.go new file mode 100644 index 00000000..9d633ecd --- /dev/null +++ b/x/bridge/types/genesis.go @@ -0,0 +1,14 @@ +package types + +// DefaultGenesis returns the default genesis state +func DefaultGenesis() *GenesisState { + return &GenesisState{ + Params: DefaultParams(), + } +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + return gs.Params.Validate() +} diff --git a/x/bridge/types/genesis.pb.go b/x/bridge/types/genesis.pb.go new file mode 100644 index 00000000..9f3d1ac3 --- /dev/null +++ b/x/bridge/types/genesis.pb.go @@ -0,0 +1,327 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/bridge/v1/genesis.proto + +package types + +import ( + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the bridge module's genesis state. +type GenesisState struct { + // params defines all the parameters of the module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_41cbd561393f12e3, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "pulsarchain.bridge.v1.GenesisState") +} + +func init() { + proto.RegisterFile("pulsarchain/bridge/v1/genesis.proto", fileDescriptor_41cbd561393f12e3) +} + +var fileDescriptor_41cbd561393f12e3 = []byte{ + // 224 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2e, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x4f, 0x2a, 0xca, 0x4c, 0x49, 0x4f, 0xd5, 0x2f, + 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, + 0x12, 0x45, 0x52, 0xa4, 0x07, 0x51, 0xa4, 0x57, 0x66, 0x28, 0x25, 0x98, 0x98, 0x9b, 0x99, 0x97, + 0xaf, 0x0f, 0x26, 0x21, 0x2a, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x4c, 0x7d, 0x10, 0x0b, + 0x2a, 0xaa, 0x84, 0xdd, 0x92, 0x82, 0xc4, 0xa2, 0xc4, 0x5c, 0xa8, 0x1d, 0x4a, 0x01, 0x5c, 0x3c, + 0xee, 0x10, 0x4b, 0x83, 0x4b, 0x12, 0x4b, 0x52, 0x85, 0x1c, 0xb8, 0xd8, 0x20, 0xf2, 0x12, 0x8c, + 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0xb2, 0x7a, 0x58, 0x1d, 0xa1, 0x17, 0x00, 0x56, 0xe4, 0xc4, 0x79, + 0xe2, 0x9e, 0x3c, 0xc3, 0x8a, 0xe7, 0x1b, 0xb4, 0x18, 0x83, 0xa0, 0xfa, 0x9c, 0xbc, 0x4f, 0x3c, + 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, + 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x30, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, + 0x2f, 0x39, 0x3f, 0x57, 0x3f, 0x2f, 0x3f, 0x25, 0xd5, 0xd0, 0xc0, 0x50, 0x37, 0x33, 0x5f, 0x1f, + 0x62, 0x81, 0x2e, 0xc4, 0x99, 0x15, 0x30, 0x87, 0x96, 0x54, 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, + 0x5d, 0x69, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x73, 0xed, 0xd3, 0x65, 0x30, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bridge/types/genesis_test.go b/x/bridge/types/genesis_test.go new file mode 100644 index 00000000..95c5c763 --- /dev/null +++ b/x/bridge/types/genesis_test.go @@ -0,0 +1,37 @@ +package types_test + +import ( + "testing" + + "github.com/node101-io/pulsar-chain/x/bridge/types" + "github.com/stretchr/testify/require" +) + +func TestGenesisState_Validate(t *testing.T) { + tests := []struct { + desc string + genState *types.GenesisState + valid bool + }{ + { + desc: "default is valid", + genState: types.DefaultGenesis(), + valid: true, + }, + { + desc: "valid genesis state", + genState: &types.GenesisState{}, + valid: true, + }, + } + for _, tc := range tests { + t.Run(tc.desc, func(t *testing.T) { + err := tc.genState.Validate() + if tc.valid { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/x/bridge/types/keys.go b/x/bridge/types/keys.go new file mode 100644 index 00000000..fc6349ad --- /dev/null +++ b/x/bridge/types/keys.go @@ -0,0 +1,19 @@ +package types + +import "cosmossdk.io/collections" + +const ( + // ModuleName defines the module name + ModuleName = "bridge" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // GovModuleName duplicates the gov module's name to avoid a dependency with x/gov. + // It should be synced with the gov module's name if it is ever changed. + // See: https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.2/x/gov/types/keys.go#L9 + GovModuleName = "gov" +) + +// ParamsKey is the prefix to retrieve all Params +var ParamsKey = collections.NewPrefix("p_bridge") diff --git a/x/bridge/types/module.pb.go b/x/bridge/types/module.pb.go new file mode 100644 index 00000000..2940c12e --- /dev/null +++ b/x/bridge/types/module.pb.go @@ -0,0 +1,325 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/bridge/module/v1/module.proto + +package types + +import ( + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "cosmossdk.io/api/cosmos/app/v1alpha1" + proto "github.com/cosmos/gogoproto/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Module is the config object for the module. +type Module struct { + // authority defines the custom module authority. + // If not set, defaults to the governance module. + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` +} + +func (m *Module) Reset() { *m = Module{} } +func (m *Module) String() string { return proto.CompactTextString(m) } +func (*Module) ProtoMessage() {} +func (*Module) Descriptor() ([]byte, []int) { + return fileDescriptor_7b90c92481b7d913, []int{0} +} +func (m *Module) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Module) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Module.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 *Module) XXX_Merge(src proto.Message) { + xxx_messageInfo_Module.Merge(m, src) +} +func (m *Module) XXX_Size() int { + return m.Size() +} +func (m *Module) XXX_DiscardUnknown() { + xxx_messageInfo_Module.DiscardUnknown(m) +} + +var xxx_messageInfo_Module proto.InternalMessageInfo + +func (m *Module) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func init() { + proto.RegisterType((*Module)(nil), "pulsarchain.bridge.module.v1.Module") +} + +func init() { + proto.RegisterFile("pulsarchain/bridge/module/v1/module.proto", fileDescriptor_7b90c92481b7d913) +} + +var fileDescriptor_7b90c92481b7d913 = []byte{ + // 209 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2c, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x4f, 0x2a, 0xca, 0x4c, 0x49, 0x4f, 0xd5, 0xcf, + 0xcd, 0x4f, 0x29, 0xcd, 0x49, 0xd5, 0x2f, 0x33, 0x84, 0xb2, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, + 0x85, 0x64, 0x90, 0x94, 0xea, 0x41, 0x94, 0xea, 0x41, 0x15, 0x94, 0x19, 0x4a, 0x29, 0x24, 0xe7, + 0x17, 0xe7, 0xe6, 0x17, 0xeb, 0x27, 0x16, 0x14, 0xe8, 0x97, 0x19, 0x26, 0xe6, 0x14, 0x64, 0x24, + 0xa2, 0xea, 0x57, 0x8a, 0xe6, 0x62, 0xf3, 0x05, 0xf3, 0x85, 0x64, 0xb8, 0x38, 0x13, 0x4b, 0x4b, + 0x32, 0xf2, 0x8b, 0x32, 0x4b, 0x2a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x10, 0x02, 0x56, + 0xc6, 0xbb, 0x0e, 0x4c, 0xbb, 0xc5, 0xa8, 0xcb, 0xa5, 0x9d, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, + 0x97, 0x9c, 0x9f, 0xab, 0x9f, 0x97, 0x9f, 0x92, 0x6a, 0x68, 0x60, 0xa8, 0x9b, 0x99, 0xaf, 0x0f, + 0x71, 0x85, 0x2e, 0xc4, 0xc5, 0x15, 0x50, 0x37, 0x3b, 0x79, 0x9f, 0x78, 0x24, 0xc7, 0x78, 0xe1, + 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, + 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x21, 0x09, 0xc6, 0xe8, 0x97, 0x54, 0x16, 0xa4, 0x16, 0x27, 0xb1, + 0x81, 0x1d, 0x6c, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x59, 0xc3, 0xa9, 0xfb, 0x1d, 0x01, 0x00, + 0x00, +} + +func (m *Module) 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 *Module) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Module) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintModule(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintModule(dAtA []byte, offset int, v uint64) int { + offset -= sovModule(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Module) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovModule(uint64(l)) + } + return n +} + +func sovModule(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozModule(x uint64) (n int) { + return sovModule(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Module) 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 ErrIntOverflowModule + } + 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: Module: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Module: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModule + } + 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 ErrInvalidLengthModule + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModule + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipModule(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModule + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipModule(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModule + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModule + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModule + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthModule + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupModule + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthModule + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthModule = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowModule = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupModule = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bridge/types/params.go b/x/bridge/types/params.go new file mode 100644 index 00000000..d7e00501 --- /dev/null +++ b/x/bridge/types/params.go @@ -0,0 +1,17 @@ +package types + +// NewParams creates a new Params instance. +func NewParams() Params { + return Params{} +} + +// DefaultParams returns a default set of parameters. +func DefaultParams() Params { + return NewParams() +} + +// Validate validates the set of params. +func (p Params) Validate() error { + + return nil +} diff --git a/x/bridge/types/params.pb.go b/x/bridge/types/params.pb.go new file mode 100644 index 00000000..c331e520 --- /dev/null +++ b/x/bridge/types/params.pb.go @@ -0,0 +1,292 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/bridge/v1/params.proto + +package types + +import ( + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Params defines the parameters for the module. +type Params struct { +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_fc1105b3434fe519, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func init() { + proto.RegisterType((*Params)(nil), "pulsarchain.bridge.v1.Params") +} + +func init() { + proto.RegisterFile("pulsarchain/bridge/v1/params.proto", fileDescriptor_fc1105b3434fe519) +} + +var fileDescriptor_fc1105b3434fe519 = []byte{ + // 187 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2a, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x4f, 0x2a, 0xca, 0x4c, 0x49, 0x4f, 0xd5, 0x2f, + 0x33, 0xd4, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, + 0x45, 0x52, 0xa3, 0x07, 0x51, 0xa3, 0x57, 0x66, 0x28, 0x25, 0x98, 0x98, 0x9b, 0x99, 0x97, 0xaf, + 0x0f, 0x26, 0x21, 0x2a, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x4c, 0x7d, 0x10, 0x0b, 0x22, + 0xaa, 0xa4, 0xc7, 0xc5, 0x16, 0x00, 0x36, 0xcf, 0x4a, 0xe5, 0xc5, 0x02, 0x79, 0xc6, 0xae, 0xe7, + 0x1b, 0xb4, 0xa4, 0x91, 0xad, 0xad, 0x80, 0x59, 0x0c, 0x51, 0xe5, 0xe4, 0x7d, 0xe2, 0x91, 0x1c, + 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, + 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x86, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, + 0xf9, 0xb9, 0xfa, 0x79, 0xf9, 0x29, 0xa9, 0x86, 0x06, 0x86, 0xba, 0x99, 0xf9, 0xfa, 0x10, 0xc3, + 0x74, 0xd1, 0x4c, 0x2b, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0xbb, 0xc1, 0x18, 0x10, 0x00, + 0x00, 0xff, 0xff, 0x2e, 0x58, 0x7b, 0x4e, 0xe9, 0x00, 0x00, 0x00, +} + +func (this *Params) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Params) + if !ok { + that2, ok := that.(Params) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintParams(dAtA []byte, offset int, v uint64) int { + offset -= sovParams(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovParams(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozParams(x uint64) (n int) { + return sovParams(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) 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 ErrIntOverflowParams + } + 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: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipParams(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthParams + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupParams + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthParams + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthParams = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowParams = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupParams = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bridge/types/query.pb.go b/x/bridge/types/query.pb.go new file mode 100644 index 00000000..7fac1117 --- /dev/null +++ b/x/bridge/types/query.pb.go @@ -0,0 +1,542 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/bridge/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryParamsRequest is request type for the Query/Params RPC method. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f0aa4d5eadeeb7a5, []int{0} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.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 *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse is response type for the Query/Params RPC method. +type QueryParamsResponse struct { + // params holds all the parameters of this module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f0aa4d5eadeeb7a5, []int{1} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.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 *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*QueryParamsRequest)(nil), "pulsarchain.bridge.v1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "pulsarchain.bridge.v1.QueryParamsResponse") +} + +func init() { proto.RegisterFile("pulsarchain/bridge/v1/query.proto", fileDescriptor_f0aa4d5eadeeb7a5) } + +var fileDescriptor_f0aa4d5eadeeb7a5 = []byte{ + // 333 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xc1, 0x4a, 0x33, 0x31, + 0x10, 0xc7, 0x37, 0x1f, 0x7c, 0x05, 0xd7, 0x93, 0x6b, 0x05, 0x29, 0xba, 0xea, 0x9e, 0x6c, 0xa5, + 0x3b, 0xa6, 0xbe, 0x80, 0xf4, 0xea, 0x45, 0x7b, 0x11, 0xbc, 0x65, 0xdb, 0x90, 0x06, 0xba, 0x99, + 0x74, 0x93, 0x2d, 0xf6, 0xea, 0x13, 0x88, 0x5e, 0x7d, 0x00, 0x8f, 0x3e, 0x46, 0x8f, 0x05, 0x2f, + 0x9e, 0x44, 0x5a, 0xc1, 0xd7, 0x90, 0x6e, 0x56, 0x50, 0x6c, 0xc1, 0x4b, 0x18, 0x26, 0xbf, 0xff, + 0x2f, 0x93, 0xf1, 0x0f, 0x74, 0x3e, 0x30, 0x2c, 0xeb, 0xf6, 0x99, 0x54, 0x90, 0x64, 0xb2, 0x27, + 0x38, 0x8c, 0x28, 0x0c, 0x73, 0x9e, 0x8d, 0x63, 0x9d, 0xa1, 0xc5, 0x60, 0xeb, 0x1b, 0x12, 0x3b, + 0x24, 0x1e, 0xd1, 0xda, 0x06, 0x4b, 0xa5, 0x42, 0x28, 0x4e, 0x47, 0xd6, 0xaa, 0x02, 0x05, 0x16, + 0x25, 0x2c, 0xaa, 0xb2, 0xbb, 0x23, 0x10, 0xc5, 0x80, 0x03, 0xd3, 0x12, 0x98, 0x52, 0x68, 0x99, + 0x95, 0xa8, 0x4c, 0x79, 0xdb, 0xe8, 0xa2, 0x49, 0xd1, 0x40, 0xc2, 0x0c, 0x77, 0xcf, 0xc2, 0x88, + 0x26, 0xdc, 0x32, 0x0a, 0x9a, 0x09, 0xa9, 0x0a, 0xb8, 0x64, 0xa3, 0xe5, 0xc3, 0x6a, 0x96, 0xb1, + 0xb4, 0xf4, 0x45, 0x55, 0x3f, 0xb8, 0x58, 0x58, 0xce, 0x8b, 0x66, 0x87, 0x0f, 0x73, 0x6e, 0x6c, + 0x74, 0xe9, 0x6f, 0xfe, 0xe8, 0x1a, 0x8d, 0xca, 0xf0, 0xe0, 0xd4, 0xaf, 0xb8, 0xf0, 0x36, 0xd9, + 0x27, 0x87, 0xeb, 0xad, 0xdd, 0x78, 0xe9, 0x5f, 0x63, 0x17, 0x6b, 0xaf, 0x4d, 0x5e, 0xf7, 0xbc, + 0xc7, 0x8f, 0xa7, 0x06, 0xe9, 0x94, 0xb9, 0xd6, 0x03, 0xf1, 0xff, 0x17, 0xe6, 0xe0, 0x8e, 0xf8, + 0x15, 0xc7, 0x05, 0xf5, 0x15, 0x9a, 0xdf, 0x83, 0xd5, 0x1a, 0x7f, 0x41, 0xdd, 0xb4, 0x11, 0xbd, + 0x79, 0x7e, 0xbf, 0xff, 0x77, 0x14, 0xd4, 0x41, 0x61, 0x8f, 0xd3, 0x63, 0xda, 0x94, 0x08, 0x2e, + 0xde, 0x5c, 0xbe, 0x93, 0xf6, 0xd9, 0x64, 0x16, 0x92, 0xe9, 0x2c, 0x24, 0x6f, 0xb3, 0x90, 0xdc, + 0xce, 0x43, 0x6f, 0x3a, 0x0f, 0xbd, 0x97, 0x79, 0xe8, 0x5d, 0x51, 0x21, 0x6d, 0x3f, 0x4f, 0xe2, + 0x2e, 0xa6, 0x2b, 0x75, 0xd7, 0x5f, 0x42, 0x3b, 0xd6, 0xdc, 0x24, 0x95, 0x62, 0xc3, 0x27, 0x9f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x2d, 0x6c, 0x0b, 0x34, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Parameters queries the parameters of the module. + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/pulsarchain.bridge.v1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Parameters queries the parameters of the module. + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pulsarchain.bridge.v1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var Query_serviceDesc = _Query_serviceDesc +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pulsarchain.bridge.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "pulsarchain/bridge/v1/query.proto", +} + +func (m *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bridge/types/query.pb.gw.go b/x/bridge/types/query.pb.gw.go new file mode 100644 index 00000000..29d59084 --- /dev/null +++ b/x/bridge/types/query.pb.gw.go @@ -0,0 +1,153 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: pulsarchain/bridge/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"node101-io", "pulsar-chain", "bridge", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage +) diff --git a/x/bridge/types/tx.pb.go b/x/bridge/types/tx.pb.go new file mode 100644 index 00000000..648f21d8 --- /dev/null +++ b/x/bridge/types/tx.pb.go @@ -0,0 +1,601 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/bridge/v1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgUpdateParams is the Msg/UpdateParams request type. +type MsgUpdateParams struct { + // authority is the address that controls the module (defaults to x/gov unless overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // params defines the module parameters to update. + // + // NOTE: All parameters must be supplied. + Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` +} + +func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } +func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParams) ProtoMessage() {} +func (*MsgUpdateParams) Descriptor() ([]byte, []int) { + return fileDescriptor_9b52d5e292e8693c, []int{0} +} +func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParams.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 *MsgUpdateParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParams.Merge(m, src) +} +func (m *MsgUpdateParams) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParams) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo + +func (m *MsgUpdateParams) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgUpdateParams) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// MsgUpdateParamsResponse defines the response structure for executing a +// MsgUpdateParams message. +type MsgUpdateParamsResponse struct { +} + +func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } +func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParamsResponse) ProtoMessage() {} +func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9b52d5e292e8693c, []int{1} +} +func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParamsResponse.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 *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) +} +func (m *MsgUpdateParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgUpdateParams)(nil), "pulsarchain.bridge.v1.MsgUpdateParams") + proto.RegisterType((*MsgUpdateParamsResponse)(nil), "pulsarchain.bridge.v1.MsgUpdateParamsResponse") +} + +func init() { proto.RegisterFile("pulsarchain/bridge/v1/tx.proto", fileDescriptor_9b52d5e292e8693c) } + +var fileDescriptor_9b52d5e292e8693c = []byte{ + // 357 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x4f, 0x2a, 0xca, 0x4c, 0x49, 0x4f, 0xd5, 0x2f, + 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x45, 0x92, 0xd7, 0x83, + 0xc8, 0xeb, 0x95, 0x19, 0x4a, 0x09, 0x26, 0xe6, 0x66, 0xe6, 0xe5, 0xeb, 0x83, 0x49, 0x88, 0x4a, + 0x29, 0xf1, 0xe4, 0xfc, 0xe2, 0xdc, 0xfc, 0x62, 0xfd, 0xdc, 0xe2, 0x74, 0x90, 0x09, 0xb9, 0xc5, + 0xe9, 0x50, 0x09, 0x49, 0x88, 0x44, 0x3c, 0x98, 0xa7, 0x0f, 0xe1, 0x40, 0xa5, 0x44, 0xd2, 0xf3, + 0xd3, 0xf3, 0x21, 0xe2, 0x20, 0x16, 0x54, 0x54, 0x09, 0xbb, 0x9b, 0x0a, 0x12, 0x8b, 0x12, 0x73, + 0xa1, 0x3a, 0x95, 0x8e, 0x30, 0x72, 0xf1, 0xfb, 0x16, 0xa7, 0x87, 0x16, 0xa4, 0x24, 0x96, 0xa4, + 0x06, 0x80, 0x65, 0x84, 0xcc, 0xb8, 0x38, 0x13, 0x4b, 0x4b, 0x32, 0xf2, 0x8b, 0x32, 0x4b, 0x2a, + 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x9d, 0x24, 0x2e, 0x6d, 0xd1, 0x15, 0x81, 0x5a, 0xe9, 0x98, + 0x92, 0x52, 0x94, 0x5a, 0x5c, 0x1c, 0x5c, 0x52, 0x94, 0x99, 0x97, 0x1e, 0x84, 0x50, 0x2a, 0xe4, + 0xc0, 0xc5, 0x06, 0x31, 0x5b, 0x82, 0x49, 0x81, 0x51, 0x83, 0xdb, 0x48, 0x56, 0x0f, 0xab, 0xa7, + 0xf5, 0x20, 0xd6, 0x38, 0x71, 0x9e, 0xb8, 0x27, 0xcf, 0xb0, 0xe2, 0xf9, 0x06, 0x2d, 0xc6, 0x20, + 0xa8, 0x3e, 0x2b, 0xf3, 0xa6, 0xe7, 0x1b, 0xb4, 0x10, 0x26, 0x76, 0x3d, 0xdf, 0xa0, 0xa5, 0x82, + 0xec, 0x89, 0x0a, 0x98, 0x37, 0xd0, 0x9c, 0xac, 0x24, 0xc9, 0x25, 0x8e, 0x26, 0x14, 0x94, 0x5a, + 0x5c, 0x90, 0x9f, 0x57, 0x9c, 0x6a, 0x54, 0xc2, 0xc5, 0xec, 0x5b, 0x9c, 0x2e, 0x94, 0xc6, 0xc5, + 0x83, 0xe2, 0x49, 0x35, 0x1c, 0x8e, 0x43, 0x33, 0x46, 0x4a, 0x8f, 0x38, 0x75, 0x30, 0xeb, 0xa4, + 0x58, 0x1b, 0x40, 0x3e, 0x72, 0xf2, 0x3e, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, + 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, + 0x28, 0xc3, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xbc, 0xfc, 0x94, + 0x54, 0x43, 0x03, 0x43, 0xdd, 0xcc, 0x7c, 0x7d, 0x88, 0x2d, 0xba, 0x68, 0xfe, 0x2c, 0xa9, 0x2c, + 0x48, 0x2d, 0x4e, 0x62, 0x03, 0xc7, 0x95, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xad, 0x91, 0x13, + 0x68, 0x65, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // UpdateParams defines a (governance) operation for updating the module + // parameters. The authority defaults to the x/gov module account. + UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/pulsarchain.bridge.v1.Msg/UpdateParams", 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 + // parameters. The authority defaults to the x/gov module account. + UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pulsarchain.bridge.v1.Msg/UpdateParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + } + return interceptor(ctx, in, info, handler) +} + +var Msg_serviceDesc = _Msg_serviceDesc +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pulsarchain.bridge.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "UpdateParams", + Handler: _Msg_UpdateParams_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "pulsarchain/bridge/v1/tx.proto", +} + +func (m *MsgUpdateParams) 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 *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParamsResponse) 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 *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgUpdateParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Params.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgUpdateParams) 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: MsgUpdateParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", 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.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParamsResponse) 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: MsgUpdateParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bridge/types/types.go b/x/bridge/types/types.go new file mode 100644 index 00000000..ab1254f4 --- /dev/null +++ b/x/bridge/types/types.go @@ -0,0 +1 @@ +package types diff --git a/x/keyregistry/types/genesis.pb.go b/x/keyregistry/types/genesis.pb.go index 38980463..892df56a 100644 --- a/x/keyregistry/types/genesis.pb.go +++ b/x/keyregistry/types/genesis.pb.go @@ -5,12 +5,13 @@ package types import ( fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/key_update_type.pb.go b/x/keyregistry/types/key_update_type.pb.go index 083028ac..e3bbb30d 100644 --- a/x/keyregistry/types/key_update_type.pb.go +++ b/x/keyregistry/types/key_update_type.pb.go @@ -5,8 +5,9 @@ package types import ( fmt "fmt" - proto "github.com/cosmos/gogoproto/proto" math "math" + + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/module.pb.go b/x/keyregistry/types/module.pb.go index c42802f0..6c939884 100644 --- a/x/keyregistry/types/module.pb.go +++ b/x/keyregistry/types/module.pb.go @@ -4,12 +4,13 @@ package types import ( - _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "cosmossdk.io/api/cosmos/app/v1alpha1" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/params.pb.go b/x/keyregistry/types/params.pb.go index 378f92bb..083d03b5 100644 --- a/x/keyregistry/types/params.pb.go +++ b/x/keyregistry/types/params.pb.go @@ -5,12 +5,13 @@ package types import ( fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/public_key_pair.pb.go b/x/keyregistry/types/public_key_pair.pb.go index db1d3fc2..4f1401fb 100644 --- a/x/keyregistry/types/public_key_pair.pb.go +++ b/x/keyregistry/types/public_key_pair.pb.go @@ -5,10 +5,11 @@ package types import ( fmt "fmt" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/query.pb.go b/x/keyregistry/types/query.pb.go index e529ad88..d45dfd2b 100644 --- a/x/keyregistry/types/query.pb.go +++ b/x/keyregistry/types/query.pb.go @@ -6,6 +6,10 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -15,9 +19,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/tx.pb.go b/x/keyregistry/types/tx.pb.go index b0b00dec..d94eed74 100644 --- a/x/keyregistry/types/tx.pb.go +++ b/x/keyregistry/types/tx.pb.go @@ -6,6 +6,10 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -15,9 +19,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/genesis.pb.go b/x/pulsar/types/genesis.pb.go index acfbe019..65be9de9 100644 --- a/x/pulsar/types/genesis.pb.go +++ b/x/pulsar/types/genesis.pb.go @@ -5,12 +5,13 @@ package types import ( fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/module.pb.go b/x/pulsar/types/module.pb.go index b7ffd5c3..eeab9504 100644 --- a/x/pulsar/types/module.pb.go +++ b/x/pulsar/types/module.pb.go @@ -4,12 +4,13 @@ package types import ( - _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "cosmossdk.io/api/cosmos/app/v1alpha1" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/params.pb.go b/x/pulsar/types/params.pb.go index 0480a17b..e7a05515 100644 --- a/x/pulsar/types/params.pb.go +++ b/x/pulsar/types/params.pb.go @@ -5,12 +5,13 @@ package types import ( fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/query.pb.go b/x/pulsar/types/query.pb.go index 0c09f00a..8df04fb5 100644 --- a/x/pulsar/types/query.pb.go +++ b/x/pulsar/types/query.pb.go @@ -6,6 +6,10 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -15,9 +19,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/tx.pb.go b/x/pulsar/types/tx.pb.go index e3271589..2f343e52 100644 --- a/x/pulsar/types/tx.pb.go +++ b/x/pulsar/types/tx.pb.go @@ -6,6 +6,10 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -15,9 +19,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/genesis.pb.go b/x/votepersistence/types/genesis.pb.go index e252c7ba..9c48d742 100644 --- a/x/votepersistence/types/genesis.pb.go +++ b/x/votepersistence/types/genesis.pb.go @@ -5,12 +5,13 @@ package types import ( fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/module.pb.go b/x/votepersistence/types/module.pb.go index 319820ca..15faa0b1 100644 --- a/x/votepersistence/types/module.pb.go +++ b/x/votepersistence/types/module.pb.go @@ -4,12 +4,13 @@ package types import ( - _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "cosmossdk.io/api/cosmos/app/v1alpha1" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/params.pb.go b/x/votepersistence/types/params.pb.go index 3d572a3f..db7a5855 100644 --- a/x/votepersistence/types/params.pb.go +++ b/x/votepersistence/types/params.pb.go @@ -5,12 +5,13 @@ package types import ( fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/query.pb.go b/x/votepersistence/types/query.pb.go index 8c9a2ecf..4fa36cb2 100644 --- a/x/votepersistence/types/query.pb.go +++ b/x/votepersistence/types/query.pb.go @@ -6,6 +6,10 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -15,9 +19,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/tx.pb.go b/x/votepersistence/types/tx.pb.go index 31772b17..c72264a0 100644 --- a/x/votepersistence/types/tx.pb.go +++ b/x/votepersistence/types/tx.pb.go @@ -6,6 +6,10 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -15,9 +19,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/vote_ext_body.pb.go b/x/votepersistence/types/vote_ext_body.pb.go index 918fd218..e5dd66b5 100644 --- a/x/votepersistence/types/vote_ext_body.pb.go +++ b/x/votepersistence/types/vote_ext_body.pb.go @@ -5,10 +5,11 @@ package types import ( fmt "fmt" - proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" + + proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. From 4d6588d884316e7e43e5f36d017f67ba9eb98a8b Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 8 May 2026 20:40:22 +0300 Subject: [PATCH 48/63] feat: initialize pushnewactions message --- proto/pulsarchain/bridge/v1/tx.proto | 16 +- .../keeper/msg_server_push_new_actions.go | 18 + x/bridge/module/autocli.go | 6 + x/bridge/module/simulation.go | 20 + x/bridge/simulation/push_new_actions.go | 32 ++ x/bridge/types/codec.go | 4 + x/bridge/types/query.pb.go | 40 +- x/bridge/types/tx.pb.go | 420 ++++++++++++++++-- x/keyregistry/types/tx.pb.go | 52 +-- 9 files changed, 535 insertions(+), 73 deletions(-) create mode 100644 x/bridge/keeper/msg_server_push_new_actions.go create mode 100644 x/bridge/simulation/push_new_actions.go diff --git a/proto/pulsarchain/bridge/v1/tx.proto b/proto/pulsarchain/bridge/v1/tx.proto index 45d49ad0..67a1912c 100644 --- a/proto/pulsarchain/bridge/v1/tx.proto +++ b/proto/pulsarchain/bridge/v1/tx.proto @@ -1,4 +1,5 @@ syntax = "proto3"; + package pulsarchain.bridge.v1; import "amino/amino.proto"; @@ -16,6 +17,9 @@ service Msg { // UpdateParams defines a (governance) operation for updating the module // parameters. The authority defaults to the x/gov module account. rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); + + // PushNewActions defines the PushNewActions RPC. + rpc PushNewActions(MsgPushNewActions) returns (MsgPushNewActionsResponse); } // MsgUpdateParams is the Msg/UpdateParams request type. @@ -27,7 +31,7 @@ message MsgUpdateParams { string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // params defines the module parameters to update. - // + // NOTE: All parameters must be supplied. Params params = 2 [ (gogoproto.nullable) = false, @@ -38,3 +42,13 @@ message MsgUpdateParams { // MsgUpdateParamsResponse defines the response structure for executing a // MsgUpdateParams message. message MsgUpdateParamsResponse {} + +// MsgPushNewActions defines the MsgPushNewActions message. +message MsgPushNewActions { + option (cosmos.msg.v1.signer) = "creator"; + string creator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + int64 mina_block_height = 2; +} + +// MsgPushNewActionsResponse defines the MsgPushNewActionsResponse message. +message MsgPushNewActionsResponse {} diff --git a/x/bridge/keeper/msg_server_push_new_actions.go b/x/bridge/keeper/msg_server_push_new_actions.go new file mode 100644 index 00000000..66ccb9c3 --- /dev/null +++ b/x/bridge/keeper/msg_server_push_new_actions.go @@ -0,0 +1,18 @@ +package keeper + +import ( + "context" + + errorsmod "cosmossdk.io/errors" + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +func (k msgServer) PushNewActions(ctx context.Context, msg *types.MsgPushNewActions) (*types.MsgPushNewActionsResponse, error) { + if _, err := k.addressCodec.StringToBytes(msg.Creator); err != nil { + return nil, errorsmod.Wrap(err, "invalid authority address") + } + + // TODO: Handle the message + + return &types.MsgPushNewActionsResponse{}, nil +} diff --git a/x/bridge/module/autocli.go b/x/bridge/module/autocli.go index 91a2868c..5257bfa7 100644 --- a/x/bridge/module/autocli.go +++ b/x/bridge/module/autocli.go @@ -28,6 +28,12 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcMethod: "UpdateParams", Skip: true, // skipped because authority gated }, + { + RpcMethod: "PushNewActions", + Use: "push-new-actions [mina-block-height]", + Short: "Send a PushNewActions tx", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "mina_block_height"}}, + }, // this line is used by ignite scaffolding # autocli/tx }, }, diff --git a/x/bridge/module/simulation.go b/x/bridge/module/simulation.go index 343f5938..7a0e68e1 100644 --- a/x/bridge/module/simulation.go +++ b/x/bridge/module/simulation.go @@ -1,9 +1,13 @@ package bridge import ( + "math/rand" + "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + bridgesimulation "github.com/node101-io/pulsar-chain/x/bridge/simulation" "github.com/node101-io/pulsar-chain/x/bridge/types" ) @@ -25,6 +29,22 @@ func (am AppModule) RegisterStoreDecoder(_ simtypes.StoreDecoderRegistry) {} // WeightedOperations returns the all the gov module operations with their respective weights. func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { operations := make([]simtypes.WeightedOperation, 0) + const ( + opWeightMsgPushNewActions = "op_weight_msg_bridge" + defaultWeightMsgPushNewActions int = 100 + ) + + var weightMsgPushNewActions int + simState.AppParams.GetOrGenerate(opWeightMsgPushNewActions, &weightMsgPushNewActions, nil, + func(_ *rand.Rand) { + weightMsgPushNewActions = defaultWeightMsgPushNewActions + }, + ) + operations = append(operations, simulation.NewWeightedOperation( + weightMsgPushNewActions, + bridgesimulation.SimulateMsgPushNewActions(am.authKeeper, am.bankKeeper, am.keeper, simState.TxConfig), + )) + return operations } diff --git a/x/bridge/simulation/push_new_actions.go b/x/bridge/simulation/push_new_actions.go new file mode 100644 index 00000000..d6cbfaa0 --- /dev/null +++ b/x/bridge/simulation/push_new_actions.go @@ -0,0 +1,32 @@ +package simulation + +import ( + "math/rand" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/node101-io/pulsar-chain/x/bridge/keeper" + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +func SimulateMsgPushNewActions( + ak types.AuthKeeper, + bk types.BankKeeper, + k keeper.Keeper, + txGen client.TxConfig, +) simtypes.Operation { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + simAccount, _ := simtypes.RandomAcc(r, accs) + msg := &types.MsgPushNewActions{ + Creator: simAccount.Address.String(), + } + + // TODO: Handle the PushNewActions simulation + + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "PushNewActions simulation not implemented"), nil, nil + } +} diff --git a/x/bridge/types/codec.go b/x/bridge/types/codec.go index 56398f5e..40883301 100644 --- a/x/bridge/types/codec.go +++ b/x/bridge/types/codec.go @@ -7,6 +7,10 @@ import ( ) func RegisterInterfaces(registrar codectypes.InterfaceRegistry) { + registrar.RegisterImplementations((*sdk.Msg)(nil), + &MsgPushNewActions{}, + ) + registrar.RegisterImplementations((*sdk.Msg)(nil), &MsgUpdateParams{}, ) diff --git a/x/bridge/types/query.pb.go b/x/bridge/types/query.pb.go index 7fac1117..426c25d5 100644 --- a/x/bridge/types/query.pb.go +++ b/x/bridge/types/query.pb.go @@ -125,26 +125,26 @@ func init() { proto.RegisterFile("pulsarchain/bridge/v1/query.proto", fileDescri var fileDescriptor_f0aa4d5eadeeb7a5 = []byte{ // 333 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xc1, 0x4a, 0x33, 0x31, - 0x10, 0xc7, 0x37, 0x1f, 0x7c, 0x05, 0xd7, 0x93, 0x6b, 0x05, 0x29, 0xba, 0xea, 0x9e, 0x6c, 0xa5, - 0x3b, 0xa6, 0xbe, 0x80, 0xf4, 0xea, 0x45, 0x7b, 0x11, 0xbc, 0x65, 0xdb, 0x90, 0x06, 0xba, 0x99, - 0x74, 0x93, 0x2d, 0xf6, 0xea, 0x13, 0x88, 0x5e, 0x7d, 0x00, 0x8f, 0x3e, 0x46, 0x8f, 0x05, 0x2f, - 0x9e, 0x44, 0x5a, 0xc1, 0xd7, 0x90, 0x6e, 0x56, 0x50, 0x6c, 0xc1, 0x4b, 0x18, 0x26, 0xbf, 0xff, - 0x2f, 0x93, 0xf1, 0x0f, 0x74, 0x3e, 0x30, 0x2c, 0xeb, 0xf6, 0x99, 0x54, 0x90, 0x64, 0xb2, 0x27, - 0x38, 0x8c, 0x28, 0x0c, 0x73, 0x9e, 0x8d, 0x63, 0x9d, 0xa1, 0xc5, 0x60, 0xeb, 0x1b, 0x12, 0x3b, - 0x24, 0x1e, 0xd1, 0xda, 0x06, 0x4b, 0xa5, 0x42, 0x28, 0x4e, 0x47, 0xd6, 0xaa, 0x02, 0x05, 0x16, - 0x25, 0x2c, 0xaa, 0xb2, 0xbb, 0x23, 0x10, 0xc5, 0x80, 0x03, 0xd3, 0x12, 0x98, 0x52, 0x68, 0x99, - 0x95, 0xa8, 0x4c, 0x79, 0xdb, 0xe8, 0xa2, 0x49, 0xd1, 0x40, 0xc2, 0x0c, 0x77, 0xcf, 0xc2, 0x88, - 0x26, 0xdc, 0x32, 0x0a, 0x9a, 0x09, 0xa9, 0x0a, 0xb8, 0x64, 0xa3, 0xe5, 0xc3, 0x6a, 0x96, 0xb1, - 0xb4, 0xf4, 0x45, 0x55, 0x3f, 0xb8, 0x58, 0x58, 0xce, 0x8b, 0x66, 0x87, 0x0f, 0x73, 0x6e, 0x6c, - 0x74, 0xe9, 0x6f, 0xfe, 0xe8, 0x1a, 0x8d, 0xca, 0xf0, 0xe0, 0xd4, 0xaf, 0xb8, 0xf0, 0x36, 0xd9, - 0x27, 0x87, 0xeb, 0xad, 0xdd, 0x78, 0xe9, 0x5f, 0x63, 0x17, 0x6b, 0xaf, 0x4d, 0x5e, 0xf7, 0xbc, - 0xc7, 0x8f, 0xa7, 0x06, 0xe9, 0x94, 0xb9, 0xd6, 0x03, 0xf1, 0xff, 0x17, 0xe6, 0xe0, 0x8e, 0xf8, - 0x15, 0xc7, 0x05, 0xf5, 0x15, 0x9a, 0xdf, 0x83, 0xd5, 0x1a, 0x7f, 0x41, 0xdd, 0xb4, 0x11, 0xbd, - 0x79, 0x7e, 0xbf, 0xff, 0x77, 0x14, 0xd4, 0x41, 0x61, 0x8f, 0xd3, 0x63, 0xda, 0x94, 0x08, 0x2e, - 0xde, 0x5c, 0xbe, 0x93, 0xf6, 0xd9, 0x64, 0x16, 0x92, 0xe9, 0x2c, 0x24, 0x6f, 0xb3, 0x90, 0xdc, - 0xce, 0x43, 0x6f, 0x3a, 0x0f, 0xbd, 0x97, 0x79, 0xe8, 0x5d, 0x51, 0x21, 0x6d, 0x3f, 0x4f, 0xe2, - 0x2e, 0xa6, 0x2b, 0x75, 0xd7, 0x5f, 0x42, 0x3b, 0xd6, 0xdc, 0x24, 0x95, 0x62, 0xc3, 0x27, 0x9f, - 0x01, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x2d, 0x6c, 0x0b, 0x34, 0x02, 0x00, 0x00, + 0x14, 0x85, 0x27, 0x3f, 0xfc, 0x05, 0xc7, 0x95, 0x63, 0x05, 0x29, 0x3a, 0xea, 0xac, 0x6c, 0xa5, + 0x73, 0x4d, 0x7d, 0x01, 0xe9, 0xd6, 0x8d, 0x76, 0x23, 0xb8, 0xcb, 0xb4, 0x21, 0x0d, 0x74, 0x72, + 0xd3, 0x49, 0xa6, 0xd8, 0xad, 0x4f, 0x20, 0xba, 0xf5, 0x01, 0x5c, 0xfa, 0x18, 0x5d, 0x16, 0xdc, + 0xb8, 0x12, 0x69, 0x05, 0x5f, 0x43, 0x3a, 0x19, 0x41, 0xb1, 0x05, 0x37, 0xe1, 0x72, 0xf2, 0x9d, + 0x93, 0x93, 0xeb, 0x1f, 0xe8, 0x7c, 0x60, 0x58, 0xd6, 0xed, 0x33, 0xa9, 0x20, 0xc9, 0x64, 0x4f, + 0x70, 0x18, 0x51, 0x18, 0xe6, 0x3c, 0x1b, 0xc7, 0x3a, 0x43, 0x8b, 0xc1, 0xd6, 0x37, 0x24, 0x76, + 0x48, 0x3c, 0xa2, 0xb5, 0x0d, 0x96, 0x4a, 0x85, 0x50, 0x9c, 0x8e, 0xac, 0x35, 0xba, 0x68, 0x52, + 0x34, 0x90, 0x30, 0xc3, 0x5d, 0x04, 0x8c, 0x68, 0xc2, 0x2d, 0xa3, 0xa0, 0x99, 0x90, 0x8a, 0x59, + 0x89, 0xaa, 0x64, 0xab, 0x02, 0x05, 0x16, 0x23, 0x2c, 0xa6, 0x52, 0xdd, 0x11, 0x88, 0x62, 0xc0, + 0x81, 0x69, 0x09, 0x4c, 0x29, 0xb4, 0x85, 0xc5, 0x94, 0xb7, 0xd1, 0xf2, 0xb2, 0x9a, 0x65, 0x2c, + 0x2d, 0x99, 0xa8, 0xea, 0x07, 0x17, 0x8b, 0x97, 0xcf, 0x0b, 0xb1, 0xc3, 0x87, 0x39, 0x37, 0x36, + 0xba, 0xf4, 0x37, 0x7f, 0xa8, 0x46, 0xa3, 0x32, 0x3c, 0x38, 0xf5, 0x2b, 0xce, 0xbc, 0x4d, 0xf6, + 0xc9, 0xe1, 0x7a, 0x6b, 0x37, 0x5e, 0xfa, 0xd7, 0xd8, 0xd9, 0xda, 0x6b, 0x93, 0xd7, 0x3d, 0xef, + 0xf1, 0xe3, 0xa9, 0x41, 0x3a, 0xa5, 0xaf, 0xf5, 0x40, 0xfc, 0xff, 0x45, 0x72, 0x70, 0x47, 0xfc, + 0x8a, 0xe3, 0x82, 0xfa, 0x8a, 0x98, 0xdf, 0xc5, 0x6a, 0x8d, 0xbf, 0xa0, 0xae, 0x6d, 0x44, 0x6f, + 0x9e, 0xdf, 0xef, 0xff, 0x1d, 0x05, 0x75, 0x50, 0xd8, 0xe3, 0xf4, 0x98, 0x36, 0x25, 0x82, 0xb3, + 0x37, 0x97, 0xef, 0xa4, 0x7d, 0x36, 0x99, 0x85, 0x64, 0x3a, 0x0b, 0xc9, 0xdb, 0x2c, 0x24, 0xb7, + 0xf3, 0xd0, 0x9b, 0xce, 0x43, 0xef, 0x65, 0x1e, 0x7a, 0x57, 0x54, 0x48, 0xdb, 0xcf, 0x93, 0xb8, + 0x8b, 0xe9, 0xca, 0xb8, 0xeb, 0xaf, 0x40, 0x3b, 0xd6, 0xdc, 0x24, 0x95, 0x62, 0xc3, 0x27, 0x9f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0x17, 0xc3, 0xc9, 0x81, 0x34, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/bridge/types/tx.pb.go b/x/bridge/types/tx.pb.go index 648f21d8..ddfbf4c4 100644 --- a/x/bridge/types/tx.pb.go +++ b/x/bridge/types/tx.pb.go @@ -36,8 +36,6 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type MsgUpdateParams struct { // authority is the address that controls the module (defaults to x/gov unless overwritten). Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - // params defines the module parameters to update. - // // NOTE: All parameters must be supplied. Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` } @@ -127,38 +125,136 @@ func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo +// MsgPushNewActions defines the MsgPushNewActions message. +type MsgPushNewActions struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + MinaBlockHeight int64 `protobuf:"varint,2,opt,name=mina_block_height,json=minaBlockHeight,proto3" json:"mina_block_height,omitempty"` +} + +func (m *MsgPushNewActions) Reset() { *m = MsgPushNewActions{} } +func (m *MsgPushNewActions) String() string { return proto.CompactTextString(m) } +func (*MsgPushNewActions) ProtoMessage() {} +func (*MsgPushNewActions) Descriptor() ([]byte, []int) { + return fileDescriptor_9b52d5e292e8693c, []int{2} +} +func (m *MsgPushNewActions) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgPushNewActions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgPushNewActions.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 *MsgPushNewActions) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgPushNewActions.Merge(m, src) +} +func (m *MsgPushNewActions) XXX_Size() int { + return m.Size() +} +func (m *MsgPushNewActions) XXX_DiscardUnknown() { + xxx_messageInfo_MsgPushNewActions.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgPushNewActions proto.InternalMessageInfo + +func (m *MsgPushNewActions) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *MsgPushNewActions) GetMinaBlockHeight() int64 { + if m != nil { + return m.MinaBlockHeight + } + return 0 +} + +// MsgPushNewActionsResponse defines the MsgPushNewActionsResponse message. +type MsgPushNewActionsResponse struct { +} + +func (m *MsgPushNewActionsResponse) Reset() { *m = MsgPushNewActionsResponse{} } +func (m *MsgPushNewActionsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgPushNewActionsResponse) ProtoMessage() {} +func (*MsgPushNewActionsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9b52d5e292e8693c, []int{3} +} +func (m *MsgPushNewActionsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgPushNewActionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgPushNewActionsResponse.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 *MsgPushNewActionsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgPushNewActionsResponse.Merge(m, src) +} +func (m *MsgPushNewActionsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgPushNewActionsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgPushNewActionsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgPushNewActionsResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgUpdateParams)(nil), "pulsarchain.bridge.v1.MsgUpdateParams") proto.RegisterType((*MsgUpdateParamsResponse)(nil), "pulsarchain.bridge.v1.MsgUpdateParamsResponse") + proto.RegisterType((*MsgPushNewActions)(nil), "pulsarchain.bridge.v1.MsgPushNewActions") + proto.RegisterType((*MsgPushNewActionsResponse)(nil), "pulsarchain.bridge.v1.MsgPushNewActionsResponse") } func init() { proto.RegisterFile("pulsarchain/bridge/v1/tx.proto", fileDescriptor_9b52d5e292e8693c) } var fileDescriptor_9b52d5e292e8693c = []byte{ - // 357 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0x28, 0xcd, 0x29, - 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x4f, 0x2a, 0xca, 0x4c, 0x49, 0x4f, 0xd5, 0x2f, - 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x45, 0x92, 0xd7, 0x83, - 0xc8, 0xeb, 0x95, 0x19, 0x4a, 0x09, 0x26, 0xe6, 0x66, 0xe6, 0xe5, 0xeb, 0x83, 0x49, 0x88, 0x4a, - 0x29, 0xf1, 0xe4, 0xfc, 0xe2, 0xdc, 0xfc, 0x62, 0xfd, 0xdc, 0xe2, 0x74, 0x90, 0x09, 0xb9, 0xc5, - 0xe9, 0x50, 0x09, 0x49, 0x88, 0x44, 0x3c, 0x98, 0xa7, 0x0f, 0xe1, 0x40, 0xa5, 0x44, 0xd2, 0xf3, - 0xd3, 0xf3, 0x21, 0xe2, 0x20, 0x16, 0x54, 0x54, 0x09, 0xbb, 0x9b, 0x0a, 0x12, 0x8b, 0x12, 0x73, - 0xa1, 0x3a, 0x95, 0x8e, 0x30, 0x72, 0xf1, 0xfb, 0x16, 0xa7, 0x87, 0x16, 0xa4, 0x24, 0x96, 0xa4, - 0x06, 0x80, 0x65, 0x84, 0xcc, 0xb8, 0x38, 0x13, 0x4b, 0x4b, 0x32, 0xf2, 0x8b, 0x32, 0x4b, 0x2a, - 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x9d, 0x24, 0x2e, 0x6d, 0xd1, 0x15, 0x81, 0x5a, 0xe9, 0x98, - 0x92, 0x52, 0x94, 0x5a, 0x5c, 0x1c, 0x5c, 0x52, 0x94, 0x99, 0x97, 0x1e, 0x84, 0x50, 0x2a, 0xe4, - 0xc0, 0xc5, 0x06, 0x31, 0x5b, 0x82, 0x49, 0x81, 0x51, 0x83, 0xdb, 0x48, 0x56, 0x0f, 0xab, 0xa7, - 0xf5, 0x20, 0xd6, 0x38, 0x71, 0x9e, 0xb8, 0x27, 0xcf, 0xb0, 0xe2, 0xf9, 0x06, 0x2d, 0xc6, 0x20, - 0xa8, 0x3e, 0x2b, 0xf3, 0xa6, 0xe7, 0x1b, 0xb4, 0x10, 0x26, 0x76, 0x3d, 0xdf, 0xa0, 0xa5, 0x82, - 0xec, 0x89, 0x0a, 0x98, 0x37, 0xd0, 0x9c, 0xac, 0x24, 0xc9, 0x25, 0x8e, 0x26, 0x14, 0x94, 0x5a, - 0x5c, 0x90, 0x9f, 0x57, 0x9c, 0x6a, 0x54, 0xc2, 0xc5, 0xec, 0x5b, 0x9c, 0x2e, 0x94, 0xc6, 0xc5, - 0x83, 0xe2, 0x49, 0x35, 0x1c, 0x8e, 0x43, 0x33, 0x46, 0x4a, 0x8f, 0x38, 0x75, 0x30, 0xeb, 0xa4, - 0x58, 0x1b, 0x40, 0x3e, 0x72, 0xf2, 0x3e, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, - 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, - 0x28, 0xc3, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xbc, 0xfc, 0x94, - 0x54, 0x43, 0x03, 0x43, 0xdd, 0xcc, 0x7c, 0x7d, 0x88, 0x2d, 0xba, 0x68, 0xfe, 0x2c, 0xa9, 0x2c, - 0x48, 0x2d, 0x4e, 0x62, 0x03, 0xc7, 0x95, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xad, 0x91, 0x13, - 0x68, 0x65, 0x02, 0x00, 0x00, + // 461 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x41, 0x6b, 0xd4, 0x40, + 0x18, 0xdd, 0xb1, 0x58, 0xd9, 0xb1, 0x58, 0x36, 0x54, 0xba, 0x1b, 0x31, 0x96, 0x20, 0xb2, 0x2c, + 0x6c, 0xa6, 0x59, 0x41, 0xa1, 0x27, 0x9b, 0x93, 0x20, 0x2b, 0x25, 0xe2, 0xc5, 0xcb, 0x32, 0x49, + 0xc6, 0xc9, 0xe0, 0x26, 0x13, 0x66, 0x26, 0xb5, 0xbd, 0xa9, 0x47, 0x4f, 0xfe, 0x0c, 0x8f, 0x7b, + 0xf0, 0x27, 0x78, 0xe8, 0xb1, 0x78, 0xf2, 0x24, 0x92, 0x3d, 0xec, 0xdf, 0x90, 0x64, 0x12, 0xda, + 0xc6, 0x96, 0xf6, 0x12, 0x32, 0xef, 0xbd, 0xef, 0x7b, 0xdf, 0x9b, 0x6f, 0xa0, 0x95, 0xe5, 0x73, + 0x89, 0x45, 0x18, 0x63, 0x96, 0xa2, 0x40, 0xb0, 0x88, 0x12, 0x74, 0xe8, 0x22, 0x75, 0xe4, 0x64, + 0x82, 0x2b, 0x6e, 0xdc, 0x3f, 0xc7, 0x3b, 0x9a, 0x77, 0x0e, 0x5d, 0xb3, 0x87, 0x13, 0x96, 0x72, + 0x54, 0x7d, 0xb5, 0xd2, 0xdc, 0x0e, 0xb9, 0x4c, 0xb8, 0x44, 0x89, 0xa4, 0x65, 0x87, 0x44, 0xd2, + 0x9a, 0x18, 0x68, 0x62, 0x56, 0x9d, 0x90, 0x3e, 0xd4, 0xd4, 0x16, 0xe5, 0x94, 0x6b, 0xbc, 0xfc, + 0xab, 0x51, 0xfb, 0xf2, 0x99, 0x32, 0x2c, 0x70, 0x52, 0x57, 0xda, 0x3f, 0x01, 0xdc, 0x9c, 0x4a, + 0xfa, 0x36, 0x8b, 0xb0, 0x22, 0x07, 0x15, 0x63, 0x3c, 0x83, 0x5d, 0x9c, 0xab, 0x98, 0x0b, 0xa6, + 0x8e, 0xfb, 0x60, 0x07, 0x0c, 0xbb, 0x5e, 0xff, 0xd7, 0x8f, 0xf1, 0x56, 0x6d, 0xb9, 0x1f, 0x45, + 0x82, 0x48, 0xf9, 0x46, 0x09, 0x96, 0x52, 0xff, 0x4c, 0x6a, 0xbc, 0x80, 0xeb, 0xba, 0x77, 0xff, + 0xd6, 0x0e, 0x18, 0xde, 0x9d, 0x3c, 0x74, 0x2e, 0x0d, 0xed, 0x68, 0x1b, 0xaf, 0x7b, 0xf2, 0xe7, + 0x51, 0xe7, 0xfb, 0x6a, 0x31, 0x02, 0x7e, 0x5d, 0xb7, 0xf7, 0xfc, 0xcb, 0x6a, 0x31, 0x3a, 0xeb, + 0xf8, 0x75, 0xb5, 0x18, 0x3d, 0x3e, 0x1f, 0xe2, 0xa8, 0x89, 0xd1, 0x1a, 0xd9, 0x1e, 0xc0, 0xed, + 0x16, 0xe4, 0x13, 0x99, 0xf1, 0x54, 0x12, 0xfb, 0x33, 0x80, 0xbd, 0xa9, 0xa4, 0x07, 0xb9, 0x8c, + 0x5f, 0x93, 0x8f, 0xfb, 0xa1, 0x62, 0x3c, 0x95, 0xc6, 0x04, 0xde, 0x09, 0x05, 0xc1, 0x8a, 0x8b, + 0x6b, 0x13, 0x36, 0x42, 0x63, 0x04, 0x7b, 0x09, 0x4b, 0xf1, 0x2c, 0x98, 0xf3, 0xf0, 0xc3, 0x2c, + 0x26, 0x8c, 0xc6, 0xaa, 0x8a, 0xba, 0xe6, 0x6f, 0x96, 0x84, 0x57, 0xe2, 0x2f, 0x2b, 0x78, 0x6f, + 0xa3, 0x4c, 0xd2, 0x54, 0xda, 0x0f, 0xe0, 0xe0, 0xbf, 0x11, 0x9a, 0x01, 0x27, 0x05, 0x80, 0x6b, + 0x53, 0x49, 0x8d, 0xf7, 0x70, 0xe3, 0xc2, 0x1a, 0x9e, 0x5c, 0x71, 0x7d, 0xad, 0xa0, 0xa6, 0x73, + 0x33, 0x5d, 0xe3, 0x67, 0xcc, 0xe1, 0xbd, 0xd6, 0x65, 0x0c, 0xaf, 0xee, 0x70, 0x51, 0x69, 0xee, + 0xde, 0x54, 0xd9, 0xb8, 0x99, 0xb7, 0x3f, 0x95, 0x1b, 0xf6, 0x5e, 0x9d, 0x14, 0x16, 0x38, 0x2d, + 0x2c, 0xf0, 0xb7, 0xb0, 0xc0, 0xb7, 0xa5, 0xd5, 0x39, 0x5d, 0x5a, 0x9d, 0xdf, 0x4b, 0xab, 0xf3, + 0xce, 0xa5, 0x4c, 0xc5, 0x79, 0xe0, 0x84, 0x3c, 0x41, 0x29, 0x8f, 0x88, 0xbb, 0xeb, 0x8e, 0x19, + 0x47, 0xda, 0x67, 0xdc, 0xda, 0xbb, 0x3a, 0xce, 0x88, 0x0c, 0xd6, 0xab, 0xb7, 0xfb, 0xf4, 0x5f, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xd6, 0xbf, 0x19, 0x10, 0x75, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -176,6 +272,8 @@ type MsgClient interface { // UpdateParams defines a (governance) operation for updating the module // parameters. The authority defaults to the x/gov module account. UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) + // PushNewActions defines the PushNewActions RPC. + PushNewActions(ctx context.Context, in *MsgPushNewActions, opts ...grpc.CallOption) (*MsgPushNewActionsResponse, error) } type msgClient struct { @@ -195,11 +293,22 @@ func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts return out, nil } +func (c *msgClient) PushNewActions(ctx context.Context, in *MsgPushNewActions, opts ...grpc.CallOption) (*MsgPushNewActionsResponse, error) { + out := new(MsgPushNewActionsResponse) + err := c.cc.Invoke(ctx, "/pulsarchain.bridge.v1.Msg/PushNewActions", 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 // parameters. The authority defaults to the x/gov module account. UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) + // PushNewActions defines the PushNewActions RPC. + PushNewActions(context.Context, *MsgPushNewActions) (*MsgPushNewActionsResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -209,6 +318,9 @@ type UnimplementedMsgServer struct { func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") } +func (*UnimplementedMsgServer) PushNewActions(ctx context.Context, req *MsgPushNewActions) (*MsgPushNewActionsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PushNewActions not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -232,6 +344,24 @@ func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +func _Msg_PushNewActions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgPushNewActions) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).PushNewActions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pulsarchain.bridge.v1.Msg/PushNewActions", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).PushNewActions(ctx, req.(*MsgPushNewActions)) + } + return interceptor(ctx, in, info, handler) +} + var Msg_serviceDesc = _Msg_serviceDesc var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "pulsarchain.bridge.v1.Msg", @@ -241,6 +371,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "UpdateParams", Handler: _Msg_UpdateParams_Handler, }, + { + MethodName: "PushNewActions", + Handler: _Msg_PushNewActions_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "pulsarchain/bridge/v1/tx.proto", @@ -309,6 +443,64 @@ func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } +func (m *MsgPushNewActions) 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 *MsgPushNewActions) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgPushNewActions) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MinaBlockHeight != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.MinaBlockHeight)) + i-- + dAtA[i] = 0x10 + } + 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 *MsgPushNewActionsResponse) 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 *MsgPushNewActionsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgPushNewActionsResponse) 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 @@ -344,6 +536,31 @@ func (m *MsgUpdateParamsResponse) Size() (n int) { return n } +func (m *MsgPushNewActions) 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)) + } + if m.MinaBlockHeight != 0 { + n += 1 + sovTx(uint64(m.MinaBlockHeight)) + } + return n +} + +func (m *MsgPushNewActionsResponse) 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 } @@ -515,6 +732,157 @@ func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgPushNewActions) 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: MsgPushNewActions: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgPushNewActions: 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 != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MinaBlockHeight", wireType) + } + m.MinaBlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MinaBlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgPushNewActionsResponse) 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: MsgPushNewActionsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgPushNewActionsResponse: 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 diff --git a/x/keyregistry/types/tx.pb.go b/x/keyregistry/types/tx.pb.go index d94eed74..6a441c46 100644 --- a/x/keyregistry/types/tx.pb.go +++ b/x/keyregistry/types/tx.pb.go @@ -389,40 +389,40 @@ var fileDescriptor_235f5fb22cc1f8d8 = []byte{ 0x04, 0x62, 0x37, 0xa9, 0xd4, 0xa1, 0x62, 0x69, 0x04, 0x53, 0x15, 0x29, 0x72, 0x61, 0x61, 0xb1, 0x2e, 0xce, 0xc9, 0x31, 0xa9, 0x7d, 0xd6, 0xdd, 0x39, 0xad, 0x37, 0xc4, 0xc8, 0xc4, 0xc7, 0x60, 0xcc, 0xc0, 0xce, 0xda, 0x09, 0x45, 0x4c, 0x0c, 0x08, 0xa1, 0x64, 0xc8, 0xd7, 0x40, 0x3e, 0xdb, - 0xb1, 0x13, 0x85, 0xa4, 0x54, 0x62, 0xb1, 0x7c, 0xef, 0xfb, 0xdc, 0xf3, 0xbc, 0xef, 0xf3, 0xde, + 0xb1, 0x13, 0x85, 0xa4, 0x54, 0x62, 0xb1, 0x7c, 0xef, 0xfb, 0xdc, 0xf3, 0xbc, 0xef, 0x73, 0xef, 0x1d, 0x78, 0xe4, 0xb8, 0x97, 0x14, 0x12, 0xbd, 0x0b, 0x4d, 0x5b, 0xe9, 0x21, 0x8f, 0x20, 0xc3, 0xa4, 0x8c, 0x78, 0x4a, 0xbf, 0xa6, 0xb0, 0x6b, 0xd9, 0x21, 0x98, 0x61, 0x31, 0x9f, 0x00, 0xc9, 0x09, 0x90, 0xdc, 0xaf, 0xe5, 0xf7, 0xa0, 0x65, 0xda, 0x58, 0xe1, 0xdf, 0x00, 0x9e, 0xcf, 0xea, 0x98, 0x5a, 0x98, 0x2a, 0x16, 0x35, 0x7c, 0x1a, 0x8b, 0x1a, 0x61, 0xe2, 0x20, 0x48, 0x68, 0x7c, - 0xa5, 0x04, 0x8b, 0x30, 0xb5, 0x6f, 0x60, 0x03, 0x07, 0x71, 0xff, 0x2f, 0x8c, 0x3e, 0x59, 0x52, - 0x9d, 0x03, 0x09, 0xb4, 0xa2, 0xed, 0x47, 0x4b, 0x80, 0x3d, 0xe4, 0x69, 0xae, 0xd3, 0x81, 0x0c, - 0x69, 0xcc, 0x73, 0x50, 0xb0, 0xa3, 0xf8, 0x55, 0x00, 0x3b, 0x4d, 0x6a, 0xbc, 0xe6, 0x89, 0x16, - 0xe7, 0x12, 0x4f, 0x40, 0x06, 0xba, 0xac, 0x8b, 0x89, 0xc9, 0xbc, 0x9c, 0x50, 0x10, 0x4a, 0x99, - 0x46, 0xee, 0xdb, 0xe7, 0xea, 0x7e, 0x58, 0xe9, 0x59, 0xa7, 0x43, 0x10, 0xa5, 0x17, 0x8c, 0x98, - 0xb6, 0xa1, 0xc6, 0x50, 0xf1, 0x25, 0xd8, 0x08, 0xaa, 0xc9, 0xa5, 0x0b, 0x42, 0xe9, 0x5e, 0xbd, - 0x28, 0xff, 0xd9, 0x30, 0x39, 0xd0, 0x6a, 0x64, 0x6e, 0x7e, 0x3e, 0x4c, 0x7d, 0x9a, 0x0c, 0x2a, - 0x82, 0x1a, 0x6e, 0x3e, 0x7d, 0xfe, 0x7e, 0x32, 0xa8, 0xc4, 0xb4, 0x1f, 0x26, 0x83, 0x4a, 0x39, - 0xd9, 0xd7, 0xf5, 0x4c, 0x67, 0x73, 0xc5, 0x17, 0x0f, 0x40, 0x76, 0x2e, 0xa4, 0x22, 0xea, 0x60, - 0x9b, 0xa2, 0xe2, 0x97, 0x34, 0xef, 0x55, 0xe5, 0x5b, 0x11, 0x39, 0x47, 0x1e, 0x15, 0xeb, 0xe0, - 0x7f, 0x9d, 0x20, 0xc8, 0x30, 0x59, 0xd9, 0x69, 0x04, 0x14, 0x2b, 0x60, 0x2f, 0x9a, 0xa0, 0xdb, + 0xa5, 0x04, 0x8b, 0x30, 0xb5, 0x6f, 0x60, 0x03, 0x07, 0x71, 0xff, 0x2f, 0x8c, 0x1e, 0x2d, 0xa9, + 0xae, 0x87, 0x3c, 0xcd, 0x75, 0x3a, 0x90, 0x21, 0x8d, 0x79, 0x0e, 0x0a, 0x77, 0x3c, 0x59, 0xb2, + 0xc3, 0x81, 0x04, 0x5a, 0xa1, 0x60, 0xf1, 0xab, 0x00, 0x76, 0x9a, 0xd4, 0x78, 0xcd, 0x19, 0x5a, + 0x3c, 0x23, 0x9e, 0x80, 0x0c, 0x74, 0x59, 0x17, 0x13, 0x93, 0x79, 0x39, 0xa1, 0x20, 0x94, 0x32, + 0x8d, 0xdc, 0xb7, 0xcf, 0xd5, 0xfd, 0xb0, 0xd2, 0xb3, 0x4e, 0x87, 0x20, 0x4a, 0x2f, 0x18, 0x31, + 0x6d, 0x43, 0x8d, 0xa1, 0xe2, 0x4b, 0xb0, 0x11, 0x70, 0xe7, 0xd2, 0x05, 0xa1, 0x74, 0xaf, 0x5e, + 0x94, 0xff, 0x6c, 0x98, 0x1c, 0x68, 0x35, 0x32, 0x37, 0x3f, 0x1f, 0xa6, 0x3e, 0x4d, 0x06, 0x15, + 0x41, 0x0d, 0x37, 0x9f, 0x3e, 0x7f, 0x3f, 0x19, 0x54, 0x62, 0xda, 0x0f, 0x93, 0x41, 0xa5, 0x9c, + 0x6c, 0xe7, 0x7a, 0xa6, 0xa1, 0xb9, 0xe2, 0x8b, 0x07, 0x20, 0x3b, 0x17, 0x52, 0x11, 0x75, 0xb0, + 0x4d, 0x51, 0xf1, 0x4b, 0x9a, 0xf7, 0xaa, 0xf2, 0xad, 0x88, 0x9c, 0x23, 0x8f, 0x8a, 0x75, 0xf0, + 0xbf, 0x4e, 0x10, 0x64, 0x98, 0xac, 0xec, 0x34, 0x02, 0x8a, 0x15, 0xb0, 0x17, 0x9d, 0xa0, 0xdb, 0xbe, 0x34, 0x75, 0xad, 0x87, 0x3c, 0xde, 0xf2, 0xa6, 0xba, 0x13, 0x24, 0x5a, 0x3c, 0x7e, 0x8e, 0x3c, 0xf1, 0x31, 0xd8, 0xb1, 0x4c, 0x1b, 0x26, 0x91, 0x6b, 0x1c, 0xb9, 0xe5, 0x87, 0x63, 0x5c, 0x19, 0xec, 0x86, 0x9c, 0xd4, 0x34, 0x6c, 0xc8, 0x5c, 0x82, 0x72, 0xff, 0x25, 0x29, 0x2f, 0xa2, 0xb0, 0x78, 0x08, 0xb6, 0x39, 0x65, 0x0c, 0x5c, 0x8f, 0x19, 0x63, 0xd8, 0x0b, 0x00, 0xa0, 0xce, - 0x30, 0xe1, 0xd3, 0xce, 0x6d, 0x14, 0x84, 0xd2, 0x76, 0xfd, 0x70, 0xd9, 0x44, 0xce, 0x7c, 0xf4, - 0x2b, 0xcf, 0x41, 0x6a, 0x06, 0x46, 0xbf, 0xa7, 0x9b, 0xfe, 0x30, 0xa2, 0xce, 0x43, 0x73, 0x93, - 0x06, 0x4e, 0xcd, 0x1d, 0xa6, 0xc1, 0xd6, 0xd4, 0xf8, 0x3b, 0x5b, 0xab, 0x80, 0x7d, 0x87, 0xa0, - 0xbe, 0x36, 0xef, 0x59, 0xe0, 0xee, 0x9e, 0x9f, 0x6b, 0xce, 0xf8, 0x56, 0x05, 0xf7, 0x6d, 0x74, - 0xa5, 0x2d, 0xf6, 0x78, 0xd7, 0x46, 0x57, 0xcd, 0xbb, 0xda, 0xfc, 0x0c, 0x88, 0x53, 0xe6, 0x79, - 0xab, 0x23, 0xe2, 0x7f, 0xeb, 0x76, 0x16, 0x3c, 0x98, 0x71, 0x34, 0xf2, 0xba, 0xfe, 0x23, 0x0d, - 0xd6, 0x9a, 0xd4, 0x10, 0x1d, 0xb0, 0x39, 0x73, 0x71, 0x9f, 0x2e, 0x13, 0x9c, 0xbb, 0x15, 0xf9, - 0xe3, 0xbf, 0x00, 0x47, 0xca, 0xbe, 0xe2, 0xcc, 0xf5, 0x59, 0xa5, 0x98, 0x04, 0xaf, 0x54, 0x5c, - 0x74, 0xae, 0xc4, 0xb7, 0x00, 0x24, 0xce, 0x54, 0xf9, 0x56, 0x45, 0x73, 0xb5, 0xda, 0xad, 0xa1, - 0x91, 0x56, 0x7e, 0xfd, 0x9d, 0xff, 0x10, 0x35, 0x5a, 0x37, 0x23, 0x49, 0x18, 0x8e, 0x24, 0xe1, - 0xd7, 0x48, 0x12, 0x3e, 0x8e, 0xa5, 0xd4, 0x70, 0x2c, 0xa5, 0xbe, 0x8f, 0xa5, 0xd4, 0x9b, 0x13, - 0xc3, 0x64, 0x5d, 0xb7, 0x2d, 0xeb, 0xd8, 0x52, 0x6c, 0xdc, 0x41, 0xb5, 0xa3, 0x5a, 0xd5, 0xc4, - 0x4a, 0x20, 0x54, 0x5d, 0xf4, 0x3c, 0xf9, 0xc7, 0x81, 0xb6, 0x37, 0xf8, 0x63, 0x7b, 0xfc, 0x3b, - 0x00, 0x00, 0xff, 0xff, 0x12, 0x10, 0x94, 0x52, 0x67, 0x06, 0x00, 0x00, + 0x30, 0xe1, 0x63, 0x91, 0xdb, 0x28, 0x08, 0xa5, 0xed, 0xfa, 0xe1, 0xb2, 0x13, 0x39, 0xf3, 0xd1, + 0xaf, 0x3c, 0x07, 0xa9, 0x19, 0x18, 0xfd, 0x9e, 0x6e, 0xfa, 0x87, 0x11, 0x75, 0x1e, 0x9a, 0x9b, + 0x34, 0x70, 0x6a, 0xee, 0x30, 0x0d, 0xb6, 0xa6, 0xc6, 0xdf, 0xd9, 0x5a, 0x05, 0xec, 0x3b, 0x04, + 0xf5, 0xb5, 0x79, 0xcf, 0x02, 0x77, 0xf7, 0xfc, 0x5c, 0x73, 0xc6, 0xb7, 0x2a, 0xb8, 0x6f, 0xa3, + 0x2b, 0x6d, 0xb1, 0xc7, 0xbb, 0x36, 0xba, 0x6a, 0xde, 0xd5, 0xe6, 0x67, 0x40, 0x9c, 0x32, 0xcf, + 0x5b, 0x1d, 0x11, 0xff, 0x5b, 0xb7, 0xb3, 0xe0, 0xc1, 0x8c, 0xa3, 0x91, 0xd7, 0xf5, 0x1f, 0x69, + 0xb0, 0xd6, 0xa4, 0x86, 0xe8, 0x80, 0xcd, 0x99, 0x8b, 0xfb, 0x74, 0x99, 0xe0, 0xdc, 0xad, 0xc8, + 0x1f, 0xff, 0x05, 0x38, 0x52, 0xf6, 0x15, 0x67, 0xae, 0xcf, 0x2a, 0xc5, 0x24, 0x78, 0xa5, 0xe2, + 0xa2, 0xb9, 0x12, 0xdf, 0x02, 0x90, 0x98, 0xa9, 0xf2, 0xad, 0x8a, 0xe6, 0x6a, 0xb5, 0x5b, 0x43, + 0x23, 0xad, 0xfc, 0xfa, 0x3b, 0xff, 0x21, 0x6a, 0xb4, 0x6e, 0x46, 0x92, 0x30, 0x1c, 0x49, 0xc2, + 0xaf, 0x91, 0x24, 0x7c, 0x1c, 0x4b, 0xa9, 0xe1, 0x58, 0x4a, 0x7d, 0x1f, 0x4b, 0xa9, 0x37, 0x27, + 0x86, 0xc9, 0xba, 0x6e, 0x5b, 0xd6, 0xb1, 0xa5, 0xd8, 0xb8, 0x83, 0x6a, 0x47, 0xb5, 0xaa, 0x89, + 0x95, 0x40, 0xa8, 0xba, 0xe8, 0x79, 0xf2, 0xc7, 0x81, 0xb6, 0x37, 0xf8, 0x63, 0x7b, 0xfc, 0x3b, + 0x00, 0x00, 0xff, 0xff, 0xa3, 0x9c, 0xc6, 0x6b, 0x67, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. From 9b853bdeed58385c5dac16832be4389e9316ff22 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 8 May 2026 22:24:11 +0300 Subject: [PATCH 49/63] feat: add BridgeState to bridge module --- api/pulsarchain/abci/payload.pb.go | 3 +- .../pulsarchain/bridge/v1/bridge_state.proto | 11 + x/bridge/keeper/keeper.go | 13 +- x/bridge/types/bridge_state.pb.go | 358 ++++++++++++++++++ x/bridge/types/genesis.pb.go | 7 +- x/bridge/types/keys.go | 1 + x/bridge/types/module.pb.go | 5 +- x/bridge/types/params.pb.go | 7 +- x/bridge/types/query.pb.go | 7 +- x/bridge/types/tx.pb.go | 7 +- x/keyregistry/types/genesis.pb.go | 7 +- x/keyregistry/types/key_update_type.pb.go | 3 +- x/keyregistry/types/module.pb.go | 5 +- x/keyregistry/types/params.pb.go | 7 +- x/keyregistry/types/public_key_pair.pb.go | 3 +- x/keyregistry/types/query.pb.go | 7 +- x/keyregistry/types/tx.pb.go | 7 +- x/pulsar/types/genesis.pb.go | 7 +- x/pulsar/types/module.pb.go | 5 +- x/pulsar/types/params.pb.go | 7 +- x/pulsar/types/query.pb.go | 7 +- x/pulsar/types/tx.pb.go | 7 +- x/votepersistence/types/genesis.pb.go | 7 +- x/votepersistence/types/module.pb.go | 5 +- x/votepersistence/types/params.pb.go | 7 +- x/votepersistence/types/query.pb.go | 7 +- x/votepersistence/types/tx.pb.go | 7 +- x/votepersistence/types/vote_ext_body.pb.go | 3 +- 28 files changed, 441 insertions(+), 86 deletions(-) create mode 100644 proto/pulsarchain/bridge/v1/bridge_state.proto create mode 100644 x/bridge/types/bridge_state.pb.go diff --git a/api/pulsarchain/abci/payload.pb.go b/api/pulsarchain/abci/payload.pb.go index f67e0ada..6adc1b07 100644 --- a/api/pulsarchain/abci/payload.pb.go +++ b/api/pulsarchain/abci/payload.pb.go @@ -5,11 +5,10 @@ package abcipb import ( fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" - - proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/proto/pulsarchain/bridge/v1/bridge_state.proto b/proto/pulsarchain/bridge/v1/bridge_state.proto new file mode 100644 index 00000000..8a346cb4 --- /dev/null +++ b/proto/pulsarchain/bridge/v1/bridge_state.proto @@ -0,0 +1,11 @@ +// proto/pulsarchain/bridge/v1/state.proto +syntax = "proto3"; +package pulsarchain.bridge.v1; + +option go_package = "github.com/node101-io/pulsar-chain/x/bridge/types"; + +message BridgeState { + int64 latest_fetched_mina_height = 1; + + bytes actions_reduced_root = 2; +} diff --git a/x/bridge/keeper/keeper.go b/x/bridge/keeper/keeper.go index 6e318cca..ebd70774 100644 --- a/x/bridge/keeper/keeper.go +++ b/x/bridge/keeper/keeper.go @@ -11,6 +11,8 @@ import ( "github.com/node101-io/pulsar-chain/x/bridge/types" ) +const BridgeStateItemName string = "bridge_state" + type Keeper struct { storeService corestore.KVStoreService cdc codec.Codec @@ -19,8 +21,9 @@ type Keeper struct { // Typically, this should be the x/gov module account. authority []byte - Schema collections.Schema - Params collections.Item[types.Params] + Schema collections.Schema + Params collections.Item[types.Params] + BridgeState collections.Item[types.BridgeState] } func NewKeeper( @@ -43,6 +46,12 @@ func NewKeeper( authority: authority, Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), + BridgeState: collections.NewItem( + sb, + types.BridgeStateKey, + BridgeStateItemName, + codec.CollValue[types.BridgeState](cdc), + ), } schema, err := sb.Build() diff --git a/x/bridge/types/bridge_state.pb.go b/x/bridge/types/bridge_state.pb.go new file mode 100644 index 00000000..9bb06648 --- /dev/null +++ b/x/bridge/types/bridge_state.pb.go @@ -0,0 +1,358 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/bridge/v1/bridge_state.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type BridgeState struct { + LatestFetchedMinaHeight int64 `protobuf:"varint,1,opt,name=latest_fetched_mina_height,json=latestFetchedMinaHeight,proto3" json:"latest_fetched_mina_height,omitempty"` + ActionsReducedRoot []byte `protobuf:"bytes,2,opt,name=actions_reduced_root,json=actionsReducedRoot,proto3" json:"actions_reduced_root,omitempty"` +} + +func (m *BridgeState) Reset() { *m = BridgeState{} } +func (m *BridgeState) String() string { return proto.CompactTextString(m) } +func (*BridgeState) ProtoMessage() {} +func (*BridgeState) Descriptor() ([]byte, []int) { + return fileDescriptor_9f537cf215cb7f9d, []int{0} +} +func (m *BridgeState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BridgeState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BridgeState.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 *BridgeState) XXX_Merge(src proto.Message) { + xxx_messageInfo_BridgeState.Merge(m, src) +} +func (m *BridgeState) XXX_Size() int { + return m.Size() +} +func (m *BridgeState) XXX_DiscardUnknown() { + xxx_messageInfo_BridgeState.DiscardUnknown(m) +} + +var xxx_messageInfo_BridgeState proto.InternalMessageInfo + +func (m *BridgeState) GetLatestFetchedMinaHeight() int64 { + if m != nil { + return m.LatestFetchedMinaHeight + } + return 0 +} + +func (m *BridgeState) GetActionsReducedRoot() []byte { + if m != nil { + return m.ActionsReducedRoot + } + return nil +} + +func init() { + proto.RegisterType((*BridgeState)(nil), "pulsarchain.bridge.v1.BridgeState") +} + +func init() { + proto.RegisterFile("pulsarchain/bridge/v1/bridge_state.proto", fileDescriptor_9f537cf215cb7f9d) +} + +var fileDescriptor_9f537cf215cb7f9d = []byte{ + // 239 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x8f, 0x31, 0x4b, 0xc4, 0x30, + 0x18, 0x86, 0x2f, 0x0a, 0x0e, 0xd5, 0xa9, 0x28, 0x1e, 0x0e, 0xe1, 0x70, 0xea, 0x72, 0xed, 0x05, + 0x47, 0xb7, 0x1b, 0x44, 0x10, 0x97, 0xba, 0xb9, 0x84, 0x34, 0xf9, 0x6c, 0x02, 0x77, 0xf9, 0x4a, + 0xf2, 0xf5, 0x50, 0xf0, 0x47, 0xf8, 0xb3, 0x1c, 0x6f, 0x74, 0x94, 0xf6, 0x8f, 0x88, 0xcd, 0x09, + 0x6e, 0xef, 0xcb, 0xf3, 0x2c, 0x4f, 0x56, 0x74, 0xfd, 0x26, 0xaa, 0xa0, 0xad, 0x72, 0xbe, 0x6a, + 0x82, 0x33, 0x2d, 0x54, 0x3b, 0x71, 0x58, 0x32, 0x92, 0x22, 0x28, 0xbb, 0x80, 0x84, 0xf9, 0xc5, + 0x3f, 0xb3, 0x4c, 0xbc, 0xdc, 0x89, 0xeb, 0xf7, 0xec, 0x74, 0x3d, 0x9d, 0xa7, 0x5f, 0x37, 0xbf, + 0xcd, 0xae, 0x36, 0x8a, 0x20, 0x92, 0x7c, 0x01, 0xd2, 0x16, 0x8c, 0xdc, 0x3a, 0xaf, 0xa4, 0x05, + 0xd7, 0x5a, 0x9a, 0xb3, 0x05, 0x2b, 0x8e, 0xeb, 0xcb, 0x64, 0xdc, 0x25, 0xe1, 0xd1, 0x79, 0x75, + 0x3f, 0xe1, 0x7c, 0x95, 0x9d, 0x2b, 0x4d, 0x0e, 0x7d, 0x94, 0x01, 0x4c, 0xaf, 0xc1, 0xc8, 0x80, + 0x48, 0xf3, 0xa3, 0x05, 0x2b, 0xce, 0xea, 0xfc, 0xc0, 0xea, 0x84, 0x6a, 0x44, 0x5a, 0x3f, 0x7c, + 0x0e, 0x9c, 0xed, 0x07, 0xce, 0xbe, 0x07, 0xce, 0x3e, 0x46, 0x3e, 0xdb, 0x8f, 0x7c, 0xf6, 0x35, + 0xf2, 0xd9, 0xb3, 0x68, 0x1d, 0xd9, 0xbe, 0x29, 0x35, 0x6e, 0x2b, 0x8f, 0x06, 0xc4, 0x4a, 0x2c, + 0x1d, 0x56, 0x29, 0x62, 0x99, 0x7a, 0x5f, 0xff, 0x8a, 0xe9, 0xad, 0x83, 0xd8, 0x9c, 0x4c, 0xa1, + 0x37, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x37, 0xe4, 0x84, 0x7a, 0x14, 0x01, 0x00, 0x00, +} + +func (m *BridgeState) 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 *BridgeState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BridgeState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ActionsReducedRoot) > 0 { + i -= len(m.ActionsReducedRoot) + copy(dAtA[i:], m.ActionsReducedRoot) + i = encodeVarintBridgeState(dAtA, i, uint64(len(m.ActionsReducedRoot))) + i-- + dAtA[i] = 0x12 + } + if m.LatestFetchedMinaHeight != 0 { + i = encodeVarintBridgeState(dAtA, i, uint64(m.LatestFetchedMinaHeight)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintBridgeState(dAtA []byte, offset int, v uint64) int { + offset -= sovBridgeState(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *BridgeState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LatestFetchedMinaHeight != 0 { + n += 1 + sovBridgeState(uint64(m.LatestFetchedMinaHeight)) + } + l = len(m.ActionsReducedRoot) + if l > 0 { + n += 1 + l + sovBridgeState(uint64(l)) + } + return n +} + +func sovBridgeState(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozBridgeState(x uint64) (n int) { + return sovBridgeState(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *BridgeState) 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 ErrIntOverflowBridgeState + } + 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: BridgeState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BridgeState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LatestFetchedMinaHeight", wireType) + } + m.LatestFetchedMinaHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBridgeState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LatestFetchedMinaHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ActionsReducedRoot", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBridgeState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthBridgeState + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthBridgeState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ActionsReducedRoot = append(m.ActionsReducedRoot[:0], dAtA[iNdEx:postIndex]...) + if m.ActionsReducedRoot == nil { + m.ActionsReducedRoot = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBridgeState(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBridgeState + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipBridgeState(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBridgeState + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBridgeState + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBridgeState + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthBridgeState + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupBridgeState + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthBridgeState + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthBridgeState = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowBridgeState = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupBridgeState = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bridge/types/genesis.pb.go b/x/bridge/types/genesis.pb.go index 9f3d1ac3..5f055299 100644 --- a/x/bridge/types/genesis.pb.go +++ b/x/bridge/types/genesis.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/bridge/types/keys.go b/x/bridge/types/keys.go index fc6349ad..c187b4ca 100644 --- a/x/bridge/types/keys.go +++ b/x/bridge/types/keys.go @@ -17,3 +17,4 @@ const ( // ParamsKey is the prefix to retrieve all Params var ParamsKey = collections.NewPrefix("p_bridge") +var BridgeStateKey = collections.NewPrefix("bridge_state") diff --git a/x/bridge/types/module.pb.go b/x/bridge/types/module.pb.go index 2940c12e..447cd299 100644 --- a/x/bridge/types/module.pb.go +++ b/x/bridge/types/module.pb.go @@ -4,13 +4,12 @@ package types import ( + _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" - - _ "cosmossdk.io/api/cosmos/app/v1alpha1" - proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/bridge/types/params.pb.go b/x/bridge/types/params.pb.go index c331e520..66ef500c 100644 --- a/x/bridge/types/params.pb.go +++ b/x/bridge/types/params.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/bridge/types/query.pb.go b/x/bridge/types/query.pb.go index 426c25d5..fc15b9e6 100644 --- a/x/bridge/types/query.pb.go +++ b/x/bridge/types/query.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/bridge/types/tx.pb.go b/x/bridge/types/tx.pb.go index ddfbf4c4..aaafc938 100644 --- a/x/bridge/types/tx.pb.go +++ b/x/bridge/types/tx.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/genesis.pb.go b/x/keyregistry/types/genesis.pb.go index 892df56a..38980463 100644 --- a/x/keyregistry/types/genesis.pb.go +++ b/x/keyregistry/types/genesis.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/key_update_type.pb.go b/x/keyregistry/types/key_update_type.pb.go index e3bbb30d..083028ac 100644 --- a/x/keyregistry/types/key_update_type.pb.go +++ b/x/keyregistry/types/key_update_type.pb.go @@ -5,9 +5,8 @@ package types import ( fmt "fmt" - math "math" - proto "github.com/cosmos/gogoproto/proto" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/module.pb.go b/x/keyregistry/types/module.pb.go index 6c939884..c42802f0 100644 --- a/x/keyregistry/types/module.pb.go +++ b/x/keyregistry/types/module.pb.go @@ -4,13 +4,12 @@ package types import ( + _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" - - _ "cosmossdk.io/api/cosmos/app/v1alpha1" - proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/params.pb.go b/x/keyregistry/types/params.pb.go index 083d03b5..378f92bb 100644 --- a/x/keyregistry/types/params.pb.go +++ b/x/keyregistry/types/params.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/public_key_pair.pb.go b/x/keyregistry/types/public_key_pair.pb.go index 4f1401fb..db1d3fc2 100644 --- a/x/keyregistry/types/public_key_pair.pb.go +++ b/x/keyregistry/types/public_key_pair.pb.go @@ -5,11 +5,10 @@ package types import ( fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" - - proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/query.pb.go b/x/keyregistry/types/query.pb.go index d45dfd2b..e529ad88 100644 --- a/x/keyregistry/types/query.pb.go +++ b/x/keyregistry/types/query.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/keyregistry/types/tx.pb.go b/x/keyregistry/types/tx.pb.go index 6a441c46..566bdba3 100644 --- a/x/keyregistry/types/tx.pb.go +++ b/x/keyregistry/types/tx.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/genesis.pb.go b/x/pulsar/types/genesis.pb.go index 65be9de9..acfbe019 100644 --- a/x/pulsar/types/genesis.pb.go +++ b/x/pulsar/types/genesis.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/module.pb.go b/x/pulsar/types/module.pb.go index eeab9504..b7ffd5c3 100644 --- a/x/pulsar/types/module.pb.go +++ b/x/pulsar/types/module.pb.go @@ -4,13 +4,12 @@ package types import ( + _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" - - _ "cosmossdk.io/api/cosmos/app/v1alpha1" - proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/params.pb.go b/x/pulsar/types/params.pb.go index e7a05515..0480a17b 100644 --- a/x/pulsar/types/params.pb.go +++ b/x/pulsar/types/params.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/query.pb.go b/x/pulsar/types/query.pb.go index 8df04fb5..0c09f00a 100644 --- a/x/pulsar/types/query.pb.go +++ b/x/pulsar/types/query.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/pulsar/types/tx.pb.go b/x/pulsar/types/tx.pb.go index 2f343e52..e3271589 100644 --- a/x/pulsar/types/tx.pb.go +++ b/x/pulsar/types/tx.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/genesis.pb.go b/x/votepersistence/types/genesis.pb.go index 9c48d742..e252c7ba 100644 --- a/x/votepersistence/types/genesis.pb.go +++ b/x/votepersistence/types/genesis.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/module.pb.go b/x/votepersistence/types/module.pb.go index 15faa0b1..319820ca 100644 --- a/x/votepersistence/types/module.pb.go +++ b/x/votepersistence/types/module.pb.go @@ -4,13 +4,12 @@ package types import ( + _ "cosmossdk.io/api/cosmos/app/v1alpha1" fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" - - _ "cosmossdk.io/api/cosmos/app/v1alpha1" - proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/params.pb.go b/x/votepersistence/types/params.pb.go index db7a5855..3d572a3f 100644 --- a/x/votepersistence/types/params.pb.go +++ b/x/votepersistence/types/params.pb.go @@ -5,13 +5,12 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/query.pb.go b/x/votepersistence/types/query.pb.go index 4fa36cb2..8c9a2ecf 100644 --- a/x/votepersistence/types/query.pb.go +++ b/x/votepersistence/types/query.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/tx.pb.go b/x/votepersistence/types/tx.pb.go index c72264a0..31772b17 100644 --- a/x/votepersistence/types/tx.pb.go +++ b/x/votepersistence/types/tx.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" @@ -19,6 +15,9 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/votepersistence/types/vote_ext_body.pb.go b/x/votepersistence/types/vote_ext_body.pb.go index e5dd66b5..918fd218 100644 --- a/x/votepersistence/types/vote_ext_body.pb.go +++ b/x/votepersistence/types/vote_ext_body.pb.go @@ -5,11 +5,10 @@ package types import ( fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" - - proto "github.com/cosmos/gogoproto/proto" ) // Reference imports to suppress errors if they are not otherwise used. From bb91832eb90eb37c3af09fca8207f1991667f28b Mon Sep 17 00:00:00 2001 From: Yusuf Date: Fri, 8 May 2026 22:32:32 +0300 Subject: [PATCH 50/63] feat: add helpers to bridge state item --- x/bridge/keeper/keeper.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/x/bridge/keeper/keeper.go b/x/bridge/keeper/keeper.go index ebd70774..4032b99a 100644 --- a/x/bridge/keeper/keeper.go +++ b/x/bridge/keeper/keeper.go @@ -1,6 +1,7 @@ package keeper import ( + "context" "fmt" "cosmossdk.io/collections" @@ -67,3 +68,11 @@ func NewKeeper( func (k Keeper) GetAuthority() []byte { return k.authority } + +func (k Keeper) GetBridgeState(ctx context.Context) (types.BridgeState, error) { + return k.BridgeState.Get(ctx) +} + +func (k Keeper) setBridgeState(ctx context.Context, st types.BridgeState) error { + return k.BridgeState.Set(ctx, st) +} From 926d677faa70cc73a920fc06f8b5d0b432238c63 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Thu, 14 May 2026 16:03:57 +0300 Subject: [PATCH 51/63] feat: enable api to allow external requests and queries --- scripts/setup_local_testnet.sh | 13 ++++-- scripts/setup_local_testnet_helper.py | 58 ++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/scripts/setup_local_testnet.sh b/scripts/setup_local_testnet.sh index 58c0a0db..341b5bde 100755 --- a/scripts/setup_local_testnet.sh +++ b/scripts/setup_local_testnet.sh @@ -18,6 +18,9 @@ VOTE_EXT_ENABLE_HEIGHT="${VOTE_EXT_ENABLE_HEIGHT:-1}" BIN_DIR="${BIN_DIR:-$HOME/go/bin}" BINARY_PATH="${BINARY_PATH:-$BIN_DIR/pulsard}" COMPAT_BINARY_PATH="${COMPAT_BINARY_PATH:-$BIN_DIR/pulsar-chaind}" +API_ENABLE="${API_ENABLE:-true}" +API_BIND_HOST="${API_BIND_HOST:-0.0.0.0}" +GRPC_BIND_HOST="${GRPC_BIND_HOST:-localhost}" DEFAULT_NODE1_MINA_PRIV_KEY="ES17xFroE2/QOa9yCLXsQ9sJMeIUVwr2ZXcdWGjNLlM=" DEFAULT_NODE2_MINA_PRIV_KEY="PKeRXivUb4gZ/nMKxUK5beEnVJwIrzN71mAf7JVKsng=" @@ -85,13 +88,16 @@ configure_node() { sed -i.bak 's|addr_book_strict = true|addr_book_strict = false|' "$home/config/config.toml" sed -i.bak 's|allow_duplicate_ip = false|allow_duplicate_ip = true|' "$home/config/config.toml" - sed -i.bak "s|address = \"tcp://localhost:1317\"|address = \"tcp://localhost:${api_port}\"|" "$home/config/app.toml" - sed -i.bak "s|address = \"localhost:9090\"|address = \"localhost:${grpc_port}\"|" "$home/config/app.toml" + sed -i.bak "s|address = \"tcp://localhost:1317\"|address = \"tcp://${API_BIND_HOST}:${api_port}\"|" "$home/config/app.toml" + sed -i.bak "s|address = \"localhost:9090\"|address = \"${GRPC_BIND_HOST}:${grpc_port}\"|" "$home/config/app.toml" python3 "$PYTHON_HELPER" update-app-config \ --app "$home/config/app.toml" \ --min-gas-price "$MIN_GAS_PRICE" \ - --mina-priv-key "$mina_priv_key" + --mina-priv-key "$mina_priv_key" \ + --api-enable "$API_ENABLE" \ + --api-address "tcp://${API_BIND_HOST}:${api_port}" \ + --grpc-address "${GRPC_BIND_HOST}:${grpc_port}" } build_persistent_peers() { @@ -251,3 +257,4 @@ echo "" echo "Validation examples:" echo " curl -s http://localhost:${NODE_RPC_PORTS[PRIMARY_NODE_INDEX]}/validators | python3 -m json.tool | grep total" echo " $BINARY_PATH query votepersistence vote-ext-body-by-height 5 --home $PRIMARY_HOME" +echo " curl -s http://${API_BIND_HOST}:${NODE_API_PORTS[PRIMARY_NODE_INDEX]}/node101-io/pulsar-chain/votepersistence/v1/vote_ext_body_by_height/5 | python3 -m json.tool" diff --git a/scripts/setup_local_testnet_helper.py b/scripts/setup_local_testnet_helper.py index 69166dbd..0b4a1259 100644 --- a/scripts/setup_local_testnet_helper.py +++ b/scripts/setup_local_testnet_helper.py @@ -31,6 +31,23 @@ def write_json(path_str: str, payload) -> None: write_text(path_str, json.dumps(payload, indent=2) + "\n") +def set_section_value(content: str, section: str, key: str, value_repr: str) -> str: + pattern = rf"(?ms)^(\[{re.escape(section)}\]\n)(.*?)(?=^\[|\Z)" + match = re.search(pattern, content) + if not match: + raise SystemExit(f"could not find [{section}] section in app config") + + section_body = match.group(2) + key_pattern = rf"(?m)^{re.escape(key)}\s*=.*$" + + if re.search(key_pattern, section_body): + section_body = re.sub(key_pattern, f"{key} = {value_repr}", section_body, count=1) + else: + section_body = section_body.rstrip() + f"\n{key} = {value_repr}\n" + + return content[: match.start(2)] + section_body + content[match.end(2) :] + + def read_mina_priv_key(config_path: str) -> int: content = read_text(config_path) match = re.search(r'vote_extension:\s*\n\s*priv_key:\s*"([^"]+)"', content) @@ -139,7 +156,14 @@ def patch_keyregistry( return 0 -def update_app_config(app_path: str, min_gas_price: str, mina_priv_key: str) -> int: +def update_app_config( + app_path: str, + min_gas_price: str, + mina_priv_key: str, + api_enable: Optional[str] = None, + api_address: Optional[str] = None, + grpc_address: Optional[str] = None, +) -> int: app_toml = read_text(app_path) app_toml = app_toml.replace( 'minimum-gas-prices = ""', @@ -159,6 +183,26 @@ def update_app_config(app_path: str, min_gas_price: str, mina_priv_key: str) -> else: app_toml = app_toml.rstrip() + f"\n\n{vote_extension_block}" + if api_enable is not None: + normalized_api_enable = api_enable.strip().lower() + if normalized_api_enable not in {"true", "false"}: + raise SystemExit( + f"--api-enable must be true or false, got: {api_enable}" + ) + app_toml = set_section_value( + app_toml, "api", "enable", normalized_api_enable + ) + + if api_address is not None: + app_toml = set_section_value( + app_toml, "api", "address", f'"{api_address}"' + ) + + if grpc_address is not None: + app_toml = set_section_value( + app_toml, "grpc", "address", f'"{grpc_address}"' + ) + write_text(app_path, app_toml) return 0 @@ -193,6 +237,9 @@ def build_parser() -> argparse.ArgumentParser: update_app.add_argument("--app", required=True) update_app.add_argument("--min-gas-price", required=True) update_app.add_argument("--mina-priv-key", required=True) + update_app.add_argument("--api-enable") + update_app.add_argument("--api-address") + update_app.add_argument("--grpc-address") return parser @@ -214,7 +261,14 @@ def main() -> int: if args.command == "patch-keyregistry": return patch_keyregistry(args.genesis, args.mina_pub_key, args.cosmos_key) if args.command == "update-app-config": - return update_app_config(args.app, args.min_gas_price, args.mina_priv_key) + return update_app_config( + args.app, + args.min_gas_price, + args.mina_priv_key, + args.api_enable, + args.api_address, + args.grpc_address, + ) parser.print_help(sys.stderr) return 1 From 0a427450a680a8b917f8b3cc31f93924adca497b Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 20 May 2026 18:19:23 +0300 Subject: [PATCH 52/63] feat: implement graphql client to fetch actions from mina --- x/bridge/keeper/mina_archive.go | 282 ++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 x/bridge/keeper/mina_archive.go diff --git a/x/bridge/keeper/mina_archive.go b/x/bridge/keeper/mina_archive.go new file mode 100644 index 00000000..b639b5c5 --- /dev/null +++ b/x/bridge/keeper/mina_archive.go @@ -0,0 +1,282 @@ +package keeper + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "strconv" +) + +var ArchiveGraphQLEndpoint = "https://devnet-archive-node-api.gcp.o1test.net" + +type GraphQLResponse struct { + Data struct { + NetworkState struct { + MaxBlockHeight struct { + PendingMaxBlockHeight int `json:"pendingMaxBlockHeight"` + } `json:"maxBlockHeight"` + } `json:"networkState"` + } `json:"data"` +} + +type GraphQLRequest struct { + Query string `json:"query"` +} + +type FetchedAction struct { + BlockHeight int + FeePayer string + actionType int + Amount int64 +} + +const ( + pulsarActionTypeIndex = 0 + pulsarActionAmountIndex = 3 + pulsarActionFieldCount = 7 +) + +type archiveActionsResponse struct { + Data archiveActionsData `json:"data"` +} + +type archiveActionsData struct { + Actions []archiveActionGroup `json:"actions"` + Blocks []archiveBlockGroup `json:"blocks"` +} + +type archiveActionGroup struct { + BlockInfo archiveActionBlockInfo `json:"blockInfo"` + ActionData []archiveActionData `json:"actionData"` +} + +type archiveActionBlockInfo struct { + Height int `json:"height"` +} + +type archiveActionData struct { + Data []string `json:"data"` + TransactionInfo archiveTransactionInfo `json:"transactionInfo"` +} + +type archiveTransactionInfo struct { + Hash string `json:"hash"` +} + +type archiveBlockGroup struct { + Transactions archiveBlockTransactions `json:"transactions"` +} + +type archiveBlockTransactions struct { + ZkappCommands []archiveZkappCommand `json:"zkappCommands"` +} + +type archiveZkappCommand struct { + Hash string `json:"hash"` + FeePayer string `json:"feePayer"` +} + +func GetMinaBlockHeight() (int64, error) { + + const query = ` +query GetMinaBlockHeights { + networkState { + maxBlockHeight { + pendingMaxBlockHeight + } + } +}` + + body, err := json.Marshal(GraphQLRequest{ + Query: query, + }) + if err != nil { + return 0, err + } + + req, err := http.NewRequest("POST", ArchiveGraphQLEndpoint, bytes.NewBuffer(body)) + if err != nil { + return 0, err + } + + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + + resp, err := client.Do(req) + if err != nil { + return 0, err + } + defer resp.Body.Close() + + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return 0, err + } + + if resp.StatusCode != http.StatusOK { + return 0, fmt.Errorf("request failed: %s\n%s", resp.Status, string(respBody)) + } + + fmt.Println(string(respBody)) + + var result GraphQLResponse + + if err := json.Unmarshal(respBody, &result); err != nil { + return 0, err + } + + return int64(result.Data.NetworkState.MaxBlockHeight.PendingMaxBlockHeight), nil +} + +func fetchActions(contractAddress string, start, end int64) ([]FetchedAction, error) { + blockLimit := int(end - start + 1) + if blockLimit < 1 { + blockLimit = 1 + } + + query := ` +query ($actionInput: ActionFilterOptionsInput!, $blockQuery: BlockQueryInput!, $blockLimit: Int!) { + actions(input: $actionInput) { + blockInfo { + height + } + actionData { + data + transactionInfo { + hash + } + } + } + blocks(query: $blockQuery, sortBy: BLOCKHEIGHT_ASC, limit: $blockLimit) { + transactions { + zkappCommands { + hash + feePayer + } + } + } +}` + + body := map[string]any{ + "query": query, + "variables": map[string]any{ + "actionInput": map[string]any{ + "address": contractAddress, + "status": "CANONICAL", + "from": start, + "to": end, + }, + "blockQuery": map[string]any{ + "blockHeight_gte": start, + "blockHeight_lt": end + 1, + "canonical": true, + "inBestChain": true, + }, + "blockLimit": blockLimit, + }, + } + + b, err := json.Marshal(body) + if err != nil { + return nil, err + } + + resp, err := http.Post(ArchiveGraphQLEndpoint, "application/json", bytes.NewReader(b)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + out, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("request failed: %s\n%s", resp.Status, string(out)) + } + + var result archiveActionsResponse + + if err := json.Unmarshal(out, &result); err != nil { + return nil, err + } + + feePayerByHash := make(map[string]string) + for _, block := range result.Data.Blocks { + for _, zkappCommand := range block.Transactions.ZkappCommands { + feePayerByHash[zkappCommand.Hash] = zkappCommand.FeePayer + } + } + + actions := make([]FetchedAction, 0) + for _, block := range result.Data.Actions { + for _, actionData := range block.ActionData { + fetchedAction, err := fetchedActionFromActionData( + block.BlockInfo.Height, + feePayerByHash[actionData.TransactionInfo.Hash], + actionData.Data, + ) + if err != nil { + return nil, err + } + if fetchedAction == nil { + continue + } + + actions = append(actions, *fetchedAction) + } + } + + return actions, nil +} + +func fetchedActionFromActionData(blockHeight int, feePayer string, data []string) (*FetchedAction, error) { + actionType, amount, err := contractActionTypeAndAmountFromActionData(data) + if err != nil { + return nil, err + } + + if actionType == UNSPECIFIED { + return nil, nil + } + + return &FetchedAction{ + BlockHeight: blockHeight, + FeePayer: feePayer, + actionType: actionType, + Amount: amount, + }, nil +} + +func contractActionTypeAndAmountFromActionData(data []string) (int, int64, error) { + if len(data) < pulsarActionFieldCount { + return 0, 0, fmt.Errorf("invalid action data length: got %d fields, expected at least %d", len(data), pulsarActionFieldCount) + } + + actionType, err := strconv.Atoi(data[pulsarActionTypeIndex]) + if err != nil { + return 0, 0, fmt.Errorf("invalid action type %q: %w", data[pulsarActionTypeIndex], err) + } + + amount, err := strconv.ParseInt(data[pulsarActionAmountIndex], 10, 64) + if err != nil { + return 0, 0, fmt.Errorf("invalid action amount %q: %w", data[pulsarActionAmountIndex], err) + } + + if amount <= 0 { + return 0, 0, fmt.Errorf("invalid non-positive action amount: %d", amount) + } + + switch actionType { + case UNSPECIFIED: + return actionType, 0, nil + case DEPOSIT, WITHDRAW: + return actionType, amount, nil + default: + return UNSPECIFIED, 0, nil + } +} From 5b0dd2793a2af2165ee361027aeedaea00f667ac Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 20 May 2026 18:25:20 +0300 Subject: [PATCH 53/63] feat: implement push new actions --- app/app_config.go | 2 + proto/pulsarchain/bridge/v1/genesis.proto | 5 + x/bridge/keeper/genesis.go | 10 + x/bridge/keeper/genesis_test.go | 4 +- x/bridge/keeper/keeper.go | 8 +- x/bridge/keeper/keeper_test.go | 2 + x/bridge/keeper/mina_archive_test.go | 35 ++++ .../keeper/msg_server_push_new_actions.go | 183 +++++++++++++++++- x/bridge/module/depinject.go | 7 +- x/bridge/types/errors.go | 7 +- x/bridge/types/expected_keepers.go | 16 +- x/bridge/types/genesis.go | 11 +- x/bridge/types/genesis.pb.go | 78 ++++++-- x/bridge/types/types.go | 4 + 14 files changed, 353 insertions(+), 19 deletions(-) create mode 100644 x/bridge/keeper/mina_archive_test.go diff --git a/app/app_config.go b/app/app_config.go index 930f0af7..efbf5dc2 100644 --- a/app/app_config.go +++ b/app/app_config.go @@ -84,6 +84,7 @@ var ( {Account: authtypes.FeeCollectorName}, {Account: distrtypes.ModuleName}, {Account: minttypes.ModuleName, Permissions: []string{authtypes.Minter}}, + {Account: bridgemoduletypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner}}, {Account: stakingtypes.BondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}}, {Account: stakingtypes.NotBondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}}, {Account: govtypes.ModuleName, Permissions: []string{authtypes.Burner}}, @@ -97,6 +98,7 @@ var ( authtypes.FeeCollectorName, distrtypes.ModuleName, minttypes.ModuleName, + bridgemoduletypes.ModuleName, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, nft.ModuleName, diff --git a/proto/pulsarchain/bridge/v1/genesis.proto b/proto/pulsarchain/bridge/v1/genesis.proto index 1b8f02e3..d6323847 100644 --- a/proto/pulsarchain/bridge/v1/genesis.proto +++ b/proto/pulsarchain/bridge/v1/genesis.proto @@ -4,6 +4,7 @@ package pulsarchain.bridge.v1; import "amino/amino.proto"; import "gogoproto/gogo.proto"; import "pulsarchain/bridge/v1/params.proto"; +import "pulsarchain/bridge/v1/bridge_state.proto"; option go_package = "github.com/node101-io/pulsar-chain/x/bridge/types"; @@ -14,4 +15,8 @@ message GenesisState { (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; + BridgeState bridge_state = 2 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; } diff --git a/x/bridge/keeper/genesis.go b/x/bridge/keeper/genesis.go index 95689ace..cc10f07a 100644 --- a/x/bridge/keeper/genesis.go +++ b/x/bridge/keeper/genesis.go @@ -8,6 +8,11 @@ import ( // InitGenesis initializes the module's state from a provided genesis state. func (k Keeper) InitGenesis(ctx context.Context, genState types.GenesisState) error { + + err := k.BridgeState.Set(ctx, genState.BridgeState) + if err != nil { + return err + } return k.Params.Set(ctx, genState.Params) } @@ -21,5 +26,10 @@ func (k Keeper) ExportGenesis(ctx context.Context) (*types.GenesisState, error) return nil, err } + genesis.BridgeState, err = k.GetBridgeState(ctx) + if err != nil { + return nil, err + } + return genesis, nil } diff --git a/x/bridge/keeper/genesis_test.go b/x/bridge/keeper/genesis_test.go index 12fb068c..0973f70d 100644 --- a/x/bridge/keeper/genesis_test.go +++ b/x/bridge/keeper/genesis_test.go @@ -10,7 +10,8 @@ import ( func TestGenesis(t *testing.T) { genesisState := types.GenesisState{ - Params: types.DefaultParams(), + Params: types.DefaultParams(), + BridgeState: types.DefaultBridgeState(), } f := initFixture(t) @@ -21,4 +22,5 @@ func TestGenesis(t *testing.T) { require.NotNil(t, got) require.EqualExportedValues(t, genesisState.Params, got.Params) + require.EqualExportedValues(t, genesisState.BridgeState, got.BridgeState) } diff --git a/x/bridge/keeper/keeper.go b/x/bridge/keeper/keeper.go index 4032b99a..34f00a69 100644 --- a/x/bridge/keeper/keeper.go +++ b/x/bridge/keeper/keeper.go @@ -25,6 +25,9 @@ type Keeper struct { Schema collections.Schema Params collections.Item[types.Params] BridgeState collections.Item[types.BridgeState] + + bankKeeper types.BankKeeper + keyRegistryKeeper types.KeyregistryKeeper } func NewKeeper( @@ -32,7 +35,8 @@ func NewKeeper( cdc codec.Codec, addressCodec address.Codec, authority []byte, - + bankKeeper types.BankKeeper, + keyRegistryKeeper types.KeyregistryKeeper, ) Keeper { if _, err := addressCodec.BytesToString(authority); err != nil { panic(fmt.Sprintf("invalid authority address %s: %s", authority, err)) @@ -53,6 +57,8 @@ func NewKeeper( BridgeStateItemName, codec.CollValue[types.BridgeState](cdc), ), + bankKeeper: bankKeeper, + keyRegistryKeeper: keyRegistryKeeper, } schema, err := sb.Build() diff --git a/x/bridge/keeper/keeper_test.go b/x/bridge/keeper/keeper_test.go index a0ace733..06bca960 100644 --- a/x/bridge/keeper/keeper_test.go +++ b/x/bridge/keeper/keeper_test.go @@ -41,6 +41,8 @@ func initFixture(t *testing.T) *fixture { encCfg.Codec, addressCodec, authority, + nil, + nil, ) // Initialize params diff --git a/x/bridge/keeper/mina_archive_test.go b/x/bridge/keeper/mina_archive_test.go new file mode 100644 index 00000000..89b98c2a --- /dev/null +++ b/x/bridge/keeper/mina_archive_test.go @@ -0,0 +1,35 @@ +package keeper + +import ( + "fmt" + "testing" + + "github.com/node101-io/pulsar-chain/x/bridge/types" +) + +func TestGetMinaBlockHeights(t *testing.T) { + heights, err := GetMinaBlockHeight() + if err != nil { + t.Fatal(err) + } + + fmt.Println("pending:", heights) +} +func TestFetchActions(t *testing.T) { + + heights := 520114 + + actions, err := fetchActions(types.ContractAddress, int64(heights-2000), int64(heights)) + if err != nil { + t.Fatal(err) + } + + fmt.Printf("%+v\n", actions) + + for _, act := range actions { + + fmt.Println(act.actionType, act.Amount, act.BlockHeight, act.FeePayer) + + } + +} diff --git a/x/bridge/keeper/msg_server_push_new_actions.go b/x/bridge/keeper/msg_server_push_new_actions.go index 66ccb9c3..efbbd5dd 100644 --- a/x/bridge/keeper/msg_server_push_new_actions.go +++ b/x/bridge/keeper/msg_server_push_new_actions.go @@ -3,16 +3,197 @@ package keeper import ( "context" + "cosmossdk.io/errors" errorsmod "cosmossdk.io/errors" + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/node101-io/pulsar-chain/x/bridge/types" + keyregistryTypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" ) +const ( + UNSPECIFIED = iota + DEPOSIT + WITHDRAW +) + +func (k *Keeper) isValid(ctx context.Context, act *FetchedAction) (bool, error) { + if k.keyRegistryKeeper == nil { + return false, types.ErrKeyRegistryKeeperNotConfigured + } + switch act.actionType { + case DEPOSIT: + return k.isValidDeposit(ctx, act) + case WITHDRAW: + return k.isValidWithdrawal(ctx, act) + default: + return false, types.ErrUnspecified + } +} + +func (k *Keeper) isValidDeposit(ctx context.Context, act *FetchedAction) (bool, error) { + + exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, []byte(act.FeePayer)) + if err != nil { + return false, err + } + if !exists { + return false, nil + } + return true, nil +} + +func (k *Keeper) isValidWithdrawal(ctx context.Context, act *FetchedAction) (bool, error) { + exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, []byte(act.FeePayer)) + if err != nil { + return false, err + } + if !exists { + return false, nil + } + + cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) + if err != nil { + return false, err + } + + addr, err := userAddressFromCosmosPubKey(cosmosPubKey) + if err != nil { + return false, err + } + + if k.bankKeeper.SpendableCoins(ctx, addr).AmountOf(types.Denom).Uint64() < uint64(act.Amount) { + return false, nil + } + + return true, nil +} + +func (k *Keeper) apply(ctx context.Context, act *FetchedAction) error { + + if k.bankKeeper == nil { + return types.ErrBankKeeperNotConfigured + } + + switch act.actionType { + case DEPOSIT: + return k.applyDeposit(ctx, act) + case WITHDRAW: + return k.applyWithdrawal(ctx, act) + default: + return types.ErrUnspecified + } +} + +func (k *Keeper) applyDeposit(ctx context.Context, act *FetchedAction) error { + + cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) + if err != nil { + return err + } + + addr, err := userAddressFromCosmosPubKey(cosmosPubKey) + if err != nil { + return err + } + + coins := sdk.NewCoins(sdk.NewCoin(types.Denom, math.NewInt(act.Amount))) + + if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil { + return err + } + + return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, coins) +} + +func (k *Keeper) applyWithdrawal(ctx context.Context, act *FetchedAction) error { + + cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) + if err != nil { + return err + } + + addr, err := userAddressFromCosmosPubKey(cosmosPubKey) + if err != nil { + return err + } + + spendableCoins := k.bankKeeper.SpendableCoins(ctx, addr) + + minaAmount := spendableCoins.AmountOf(types.Denom) + + err = spendableCoins.Validate() + if err != nil { + return err + } + + if minaAmount.Uint64() < uint64(act.Amount) { + return types.ErrNotEnoughBalance + } + + coins := sdk.NewCoins(sdk.NewCoin(types.Denom, math.NewInt(act.Amount))) + + if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, coins); err != nil { + return err + } + + return k.bankKeeper.BurnCoins(ctx, types.ModuleName, coins) +} + +func userAddressFromCosmosPubKey(cosmosPubKey []byte) (sdk.AccAddress, error) { + if len(cosmosPubKey) != secp256k1.PubKeySize { + return nil, errors.Wrap(keyregistryTypes.ErrInvalidPublicKey, "user cosmos public key must be compressed secp256k1 (33 bytes)") + } + + pubKey := secp256k1.PubKey{Key: cosmosPubKey} + + return sdk.AccAddress(pubKey.Address()), nil +} + func (k msgServer) PushNewActions(ctx context.Context, msg *types.MsgPushNewActions) (*types.MsgPushNewActionsResponse, error) { if _, err := k.addressCodec.StringToBytes(msg.Creator); err != nil { return nil, errorsmod.Wrap(err, "invalid authority address") } - // TODO: Handle the message + currentMinaBlockHeight, err := GetMinaBlockHeight() + if err != nil { + return nil, err + } + + bridgeState, err := k.Keeper.GetBridgeState(ctx) + if err != nil { + return nil, err + } + + if currentMinaBlockHeight-msg.MinaBlockHeight < types.MINA_HARDFINALITY_BLOCK_DURATION { + return nil, types.ErrMinaBlockNotFinalized + } + + actions, err := fetchActions(types.ContractAddress, bridgeState.LatestFetchedMinaHeight, msg.MinaBlockHeight) + if err != nil { + return nil, err + } + for _, act := range actions { + + valid, err := k.isValid(ctx, &act) + if err != nil { + return nil, err + } + if !valid { + continue + } + if err := k.apply(ctx, &act); err != nil { + return nil, err + } + } + + if err := k.Keeper.setBridgeState(ctx, types.BridgeState{ + LatestFetchedMinaHeight: msg.MinaBlockHeight, + ActionsReducedRoot: []byte(""), + }); err != nil { + return nil, err + } return &types.MsgPushNewActionsResponse{}, nil } diff --git a/x/bridge/module/depinject.go b/x/bridge/module/depinject.go index 4b12ff91..d0c982c1 100644 --- a/x/bridge/module/depinject.go +++ b/x/bridge/module/depinject.go @@ -33,8 +33,9 @@ type ModuleInputs struct { Cdc codec.Codec AddressCodec address.Codec - AuthKeeper types.AuthKeeper - BankKeeper types.BankKeeper + AuthKeeper types.AuthKeeper + BankKeeper types.BankKeeper + KeyregistryKeeper types.KeyregistryKeeper } type ModuleOutputs struct { @@ -55,6 +56,8 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.Cdc, in.AddressCodec, authority, + in.BankKeeper, + in.KeyregistryKeeper, ) m := NewAppModule(in.Cdc, k, in.AuthKeeper, in.BankKeeper) diff --git a/x/bridge/types/errors.go b/x/bridge/types/errors.go index ea1915d2..cb4be4fc 100644 --- a/x/bridge/types/errors.go +++ b/x/bridge/types/errors.go @@ -8,5 +8,10 @@ import ( // x/bridge module sentinel errors var ( - ErrInvalidSigner = errors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") + ErrInvalidSigner = errors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") + ErrUnspecified = errors.Register(ModuleName, 1101, "unspecified action type") + ErrNotEnoughBalance = errors.Register(ModuleName, 1102, "not enough balance") + ErrBankKeeperNotConfigured = errors.Register(ModuleName, 1103, "bank keeper is not configured") + ErrKeyRegistryKeeperNotConfigured = errors.Register(ModuleName, 1104, "keyregistry keeper is not configured") + ErrMinaBlockNotFinalized = errors.Register(ModuleName, 1105, "mina block not finalized") ) diff --git a/x/bridge/types/expected_keepers.go b/x/bridge/types/expected_keepers.go index b175461c..f4e8e9f6 100644 --- a/x/bridge/types/expected_keepers.go +++ b/x/bridge/types/expected_keepers.go @@ -17,7 +17,21 @@ type AuthKeeper interface { // BankKeeper defines the expected interface for the Bank module. type BankKeeper interface { SpendableCoins(context.Context, sdk.AccAddress) sdk.Coins - // Methods imported from bank should be defined here + SendCoinsFromModuleToAccount(context.Context, string, sdk.AccAddress, sdk.Coins) error + SendCoinsFromAccountToModule(context.Context, sdk.AccAddress, string, sdk.Coins) error + MintCoins(context.Context, string, sdk.Coins) error + BurnCoins(context.Context, string, sdk.Coins) error +} + +// KeyregistryKeeper defines the expected interface for the Keyregistry module. +type KeyregistryKeeper interface { + UserGetMinaToCosmos(context.Context, []byte) ([]byte, error) + UserMinaToCosmosHas(context.Context, []byte) (bool, error) + UserCosmosToMinaHas(context.Context, []byte) (bool, error) + + ValidatorGetMinaToCosmos(context.Context, []byte) ([]byte, error) + ValidatorMinaToCosmosHas(context.Context, []byte) (bool, error) + ValidatorCosmosToMinaHas(context.Context, []byte) (bool, error) } // ParamSubspace defines the expected Subspace interface for parameters. diff --git a/x/bridge/types/genesis.go b/x/bridge/types/genesis.go index 9d633ecd..be6e2eea 100644 --- a/x/bridge/types/genesis.go +++ b/x/bridge/types/genesis.go @@ -3,7 +3,8 @@ package types // DefaultGenesis returns the default genesis state func DefaultGenesis() *GenesisState { return &GenesisState{ - Params: DefaultParams(), + Params: DefaultParams(), + BridgeState: DefaultBridgeState(), } } @@ -12,3 +13,11 @@ func DefaultGenesis() *GenesisState { func (gs GenesisState) Validate() error { return gs.Params.Validate() } + +func DefaultBridgeState() BridgeState { + + return BridgeState{ + LatestFetchedMinaHeight: 0, + ActionsReducedRoot: nil, + } +} diff --git a/x/bridge/types/genesis.pb.go b/x/bridge/types/genesis.pb.go index 5f055299..1017849c 100644 --- a/x/bridge/types/genesis.pb.go +++ b/x/bridge/types/genesis.pb.go @@ -27,7 +27,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the bridge module's genesis state. type GenesisState struct { // params defines all the parameters of the module. - Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + BridgeState BridgeState `protobuf:"bytes,2,opt,name=bridge_state,json=bridgeState,proto3" json:"bridge_state"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -70,6 +71,13 @@ func (m *GenesisState) GetParams() Params { return Params{} } +func (m *GenesisState) GetBridgeState() BridgeState { + if m != nil { + return m.BridgeState + } + return BridgeState{} +} + func init() { proto.RegisterType((*GenesisState)(nil), "pulsarchain.bridge.v1.GenesisState") } @@ -79,21 +87,24 @@ func init() { } var fileDescriptor_41cbd561393f12e3 = []byte{ - // 224 bytes of a gzipped FileDescriptorProto + // 262 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2e, 0x28, 0xcd, 0x29, 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x4f, 0x2a, 0xca, 0x4c, 0x49, 0x4f, 0xd5, 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x45, 0x52, 0xa4, 0x07, 0x51, 0xa4, 0x57, 0x66, 0x28, 0x25, 0x98, 0x98, 0x9b, 0x99, 0x97, 0xaf, 0x0f, 0x26, 0x21, 0x2a, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x4c, 0x7d, 0x10, 0x0b, - 0x2a, 0xaa, 0x84, 0xdd, 0x92, 0x82, 0xc4, 0xa2, 0xc4, 0x5c, 0xa8, 0x1d, 0x4a, 0x01, 0x5c, 0x3c, - 0xee, 0x10, 0x4b, 0x83, 0x4b, 0x12, 0x4b, 0x52, 0x85, 0x1c, 0xb8, 0xd8, 0x20, 0xf2, 0x12, 0x8c, - 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0xb2, 0x7a, 0x58, 0x1d, 0xa1, 0x17, 0x00, 0x56, 0xe4, 0xc4, 0x79, - 0xe2, 0x9e, 0x3c, 0xc3, 0x8a, 0xe7, 0x1b, 0xb4, 0x18, 0x83, 0xa0, 0xfa, 0x9c, 0xbc, 0x4f, 0x3c, - 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, - 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x30, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, - 0x2f, 0x39, 0x3f, 0x57, 0x3f, 0x2f, 0x3f, 0x25, 0xd5, 0xd0, 0xc0, 0x50, 0x37, 0x33, 0x5f, 0x1f, - 0x62, 0x81, 0x2e, 0xc4, 0x99, 0x15, 0x30, 0x87, 0x96, 0x54, 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, - 0x5d, 0x69, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x73, 0xed, 0xd3, 0x65, 0x30, 0x01, 0x00, 0x00, + 0x2a, 0xaa, 0x84, 0xdd, 0x92, 0x82, 0xc4, 0xa2, 0xc4, 0x5c, 0xa8, 0x1d, 0x52, 0x1a, 0xd8, 0xd5, + 0x40, 0x58, 0xf1, 0xc5, 0x25, 0x89, 0x25, 0xa9, 0x10, 0x95, 0x4a, 0x8b, 0x18, 0xb9, 0x78, 0xdc, + 0x21, 0xee, 0x0b, 0x06, 0x09, 0x0b, 0x39, 0x70, 0xb1, 0x41, 0x8c, 0x92, 0x60, 0x54, 0x60, 0xd4, + 0xe0, 0x36, 0x92, 0xd5, 0xc3, 0xea, 0x5e, 0xbd, 0x00, 0xb0, 0x22, 0x27, 0xce, 0x13, 0xf7, 0xe4, + 0x19, 0x56, 0x3c, 0xdf, 0xa0, 0xc5, 0x18, 0x04, 0xd5, 0x27, 0x14, 0xc0, 0xc5, 0x83, 0x6c, 0x91, + 0x04, 0x13, 0xd8, 0x1c, 0x25, 0x1c, 0xe6, 0x38, 0x81, 0x59, 0x60, 0xbb, 0x91, 0x0d, 0xe3, 0x4e, + 0x42, 0x12, 0xf7, 0x3e, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, + 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xc3, 0xf4, + 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xbc, 0xfc, 0x94, 0x54, 0x43, 0x03, + 0x43, 0xdd, 0xcc, 0x7c, 0x7d, 0x88, 0x55, 0xba, 0x10, 0xff, 0x57, 0xc0, 0x42, 0xa0, 0xa4, 0xb2, + 0x20, 0xb5, 0x38, 0x89, 0x0d, 0xec, 0x71, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x65, 0xf3, + 0x37, 0x06, 0xad, 0x01, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -116,6 +127,16 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.BridgeState.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 { size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -148,6 +169,8 @@ func (m *GenesisState) Size() (n int) { _ = l l = m.Params.Size() n += 1 + l + sovGenesis(uint64(l)) + l = m.BridgeState.Size() + n += 1 + l + sovGenesis(uint64(l)) return n } @@ -219,6 +242,39 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BridgeState", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BridgeState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/bridge/types/types.go b/x/bridge/types/types.go index ab1254f4..631be69a 100644 --- a/x/bridge/types/types.go +++ b/x/bridge/types/types.go @@ -1 +1,5 @@ package types + +const MINA_HARDFINALITY_BLOCK_DURATION int64 = 32 +const Denom string = "pMina" +const ContractAddress string = "B62qmxfmpgjKrHp31TDzDsSGpNhBEK3To1gVxMGPyBD9BZQi2ctexm4" From 320e14ec110bc08887de64c47597cdcf3de2fec5 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 20 May 2026 19:26:47 +0300 Subject: [PATCH 54/63] chore: move helpers to different file --- x/bridge/keeper/helpers_push_new_actions.go | 151 ++++++++++++++++++ .../keeper/msg_server_push_new_actions.go | 144 ----------------- 2 files changed, 151 insertions(+), 144 deletions(-) create mode 100644 x/bridge/keeper/helpers_push_new_actions.go diff --git a/x/bridge/keeper/helpers_push_new_actions.go b/x/bridge/keeper/helpers_push_new_actions.go new file mode 100644 index 00000000..839ce56d --- /dev/null +++ b/x/bridge/keeper/helpers_push_new_actions.go @@ -0,0 +1,151 @@ +package keeper + +import ( + "context" + + "cosmossdk.io/errors" + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/node101-io/pulsar-chain/x/bridge/types" + keyregistryTypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" +) + +const ( + UNSPECIFIED = iota + DEPOSIT + WITHDRAW +) + +func (k *Keeper) isValid(ctx context.Context, act *FetchedAction) (bool, error) { + if k.keyRegistryKeeper == nil { + return false, types.ErrKeyRegistryKeeperNotConfigured + } + switch act.actionType { + case DEPOSIT: + return k.isValidDeposit(ctx, act) + case WITHDRAW: + return k.isValidWithdrawal(ctx, act) + default: + return false, types.ErrUnspecified + } +} + +func (k *Keeper) isValidDeposit(ctx context.Context, act *FetchedAction) (bool, error) { + + exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, []byte(act.FeePayer)) + if err != nil { + return false, err + } + if !exists { + return false, nil + } + return true, nil +} + +func (k *Keeper) isValidWithdrawal(ctx context.Context, act *FetchedAction) (bool, error) { + exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, []byte(act.FeePayer)) + if err != nil { + return false, err + } + if !exists { + return false, nil + } + + cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) + if err != nil { + return false, err + } + + addr, err := userAddressFromCosmosPubKey(cosmosPubKey) + if err != nil { + return false, err + } + + if k.bankKeeper.SpendableCoins(ctx, addr).AmountOf(types.Denom).Uint64() < uint64(act.Amount) { + return false, nil + } + + return true, nil +} + +func (k *Keeper) apply(ctx context.Context, act *FetchedAction) error { + + if k.bankKeeper == nil { + return types.ErrBankKeeperNotConfigured + } + + switch act.actionType { + case DEPOSIT: + return k.applyDeposit(ctx, act) + case WITHDRAW: + return k.applyWithdrawal(ctx, act) + default: + return types.ErrUnspecified + } +} + +func (k *Keeper) applyDeposit(ctx context.Context, act *FetchedAction) error { + + cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) + if err != nil { + return err + } + + addr, err := userAddressFromCosmosPubKey(cosmosPubKey) + if err != nil { + return err + } + + coins := sdk.NewCoins(sdk.NewCoin(types.Denom, math.NewInt(act.Amount))) + + if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil { + return err + } + + return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, coins) +} + +func (k *Keeper) applyWithdrawal(ctx context.Context, act *FetchedAction) error { + + cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) + if err != nil { + return err + } + + addr, err := userAddressFromCosmosPubKey(cosmosPubKey) + if err != nil { + return err + } + + spendableCoins := k.bankKeeper.SpendableCoins(ctx, addr) + + minaAmount := spendableCoins.AmountOf(types.Denom) + + err = spendableCoins.Validate() + if err != nil { + return err + } + + if minaAmount.Uint64() < uint64(act.Amount) { + return types.ErrNotEnoughBalance + } + + coins := sdk.NewCoins(sdk.NewCoin(types.Denom, math.NewInt(act.Amount))) + + if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, coins); err != nil { + return err + } + + return k.bankKeeper.BurnCoins(ctx, types.ModuleName, coins) +} + +func userAddressFromCosmosPubKey(cosmosPubKey []byte) (sdk.AccAddress, error) { + if len(cosmosPubKey) != secp256k1.PubKeySize { + return nil, errors.Wrap(keyregistryTypes.ErrInvalidPublicKey, "user cosmos public key must be compressed secp256k1 (33 bytes)") + } + + pubKey := secp256k1.PubKey{Key: cosmosPubKey} + + return sdk.AccAddress(pubKey.Address()), nil +} diff --git a/x/bridge/keeper/msg_server_push_new_actions.go b/x/bridge/keeper/msg_server_push_new_actions.go index efbbd5dd..027d9770 100644 --- a/x/bridge/keeper/msg_server_push_new_actions.go +++ b/x/bridge/keeper/msg_server_push_new_actions.go @@ -3,154 +3,10 @@ package keeper import ( "context" - "cosmossdk.io/errors" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/node101-io/pulsar-chain/x/bridge/types" - keyregistryTypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" ) -const ( - UNSPECIFIED = iota - DEPOSIT - WITHDRAW -) - -func (k *Keeper) isValid(ctx context.Context, act *FetchedAction) (bool, error) { - if k.keyRegistryKeeper == nil { - return false, types.ErrKeyRegistryKeeperNotConfigured - } - switch act.actionType { - case DEPOSIT: - return k.isValidDeposit(ctx, act) - case WITHDRAW: - return k.isValidWithdrawal(ctx, act) - default: - return false, types.ErrUnspecified - } -} - -func (k *Keeper) isValidDeposit(ctx context.Context, act *FetchedAction) (bool, error) { - - exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, []byte(act.FeePayer)) - if err != nil { - return false, err - } - if !exists { - return false, nil - } - return true, nil -} - -func (k *Keeper) isValidWithdrawal(ctx context.Context, act *FetchedAction) (bool, error) { - exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, []byte(act.FeePayer)) - if err != nil { - return false, err - } - if !exists { - return false, nil - } - - cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) - if err != nil { - return false, err - } - - addr, err := userAddressFromCosmosPubKey(cosmosPubKey) - if err != nil { - return false, err - } - - if k.bankKeeper.SpendableCoins(ctx, addr).AmountOf(types.Denom).Uint64() < uint64(act.Amount) { - return false, nil - } - - return true, nil -} - -func (k *Keeper) apply(ctx context.Context, act *FetchedAction) error { - - if k.bankKeeper == nil { - return types.ErrBankKeeperNotConfigured - } - - switch act.actionType { - case DEPOSIT: - return k.applyDeposit(ctx, act) - case WITHDRAW: - return k.applyWithdrawal(ctx, act) - default: - return types.ErrUnspecified - } -} - -func (k *Keeper) applyDeposit(ctx context.Context, act *FetchedAction) error { - - cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) - if err != nil { - return err - } - - addr, err := userAddressFromCosmosPubKey(cosmosPubKey) - if err != nil { - return err - } - - coins := sdk.NewCoins(sdk.NewCoin(types.Denom, math.NewInt(act.Amount))) - - if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil { - return err - } - - return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, coins) -} - -func (k *Keeper) applyWithdrawal(ctx context.Context, act *FetchedAction) error { - - cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) - if err != nil { - return err - } - - addr, err := userAddressFromCosmosPubKey(cosmosPubKey) - if err != nil { - return err - } - - spendableCoins := k.bankKeeper.SpendableCoins(ctx, addr) - - minaAmount := spendableCoins.AmountOf(types.Denom) - - err = spendableCoins.Validate() - if err != nil { - return err - } - - if minaAmount.Uint64() < uint64(act.Amount) { - return types.ErrNotEnoughBalance - } - - coins := sdk.NewCoins(sdk.NewCoin(types.Denom, math.NewInt(act.Amount))) - - if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, coins); err != nil { - return err - } - - return k.bankKeeper.BurnCoins(ctx, types.ModuleName, coins) -} - -func userAddressFromCosmosPubKey(cosmosPubKey []byte) (sdk.AccAddress, error) { - if len(cosmosPubKey) != secp256k1.PubKeySize { - return nil, errors.Wrap(keyregistryTypes.ErrInvalidPublicKey, "user cosmos public key must be compressed secp256k1 (33 bytes)") - } - - pubKey := secp256k1.PubKey{Key: cosmosPubKey} - - return sdk.AccAddress(pubKey.Address()), nil -} - func (k msgServer) PushNewActions(ctx context.Context, msg *types.MsgPushNewActions) (*types.MsgPushNewActionsResponse, error) { if _, err := k.addressCodec.StringToBytes(msg.Creator); err != nil { return nil, errorsmod.Wrap(err, "invalid authority address") From c543f1deb972bf70b936f99dde974f2ab61a7504 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 1 Jun 2026 13:28:14 +0300 Subject: [PATCH 55/63] fix: remove pre-merge files --- abci/helpers.go | 376 ------------------ scripts/derive_mina_pub.go | 31 -- .../keeper/query_vote_ext_body_by_height.go | 113 ------ .../query_vote_ext_body_by_height_test.go | 244 ------------ 4 files changed, 764 deletions(-) delete mode 100644 abci/helpers.go delete mode 100644 scripts/derive_mina_pub.go delete mode 100644 x/votepersistence/keeper/query_vote_ext_body_by_height.go delete mode 100644 x/votepersistence/keeper/query_vote_ext_body_by_height_test.go diff --git a/abci/helpers.go b/abci/helpers.go deleted file mode 100644 index bca4d0b7..00000000 --- a/abci/helpers.go +++ /dev/null @@ -1,376 +0,0 @@ -package vote_ext - -import ( - "bytes" - "encoding/hex" - "math/big" - "sort" - - abci "github.com/cometbft/cometbft/abci/types" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - sdk "github.com/cosmos/cosmos-sdk/types" - stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/node101-io/mina-signer-go/constants" - "github.com/node101-io/mina-signer-go/field" - "github.com/node101-io/mina-signer-go/keys" - "github.com/node101-io/mina-signer-go/poseidon" - minasignature "github.com/node101-io/mina-signer-go/signature" - abcipb "github.com/node101-io/pulsar-chain/api/pulsarchain/abci" - "github.com/node101-io/pulsar-chain/x/keyregistry/types" - votepersistenceTypes "github.com/node101-io/pulsar-chain/x/votepersistence/types" -) - -func (s *SecondaryKey) SignVoteExtBody(voteExtBody votepersistenceTypes.VoteExtBody) []byte { - if s == nil || s.SecretKey == nil { - return nil - } - - msg, err := voteExtBody.Marshal() - if err != nil { - return nil - } - - sig, err := s.SecretKey.SignMessage(hex.EncodeToString(msg), NetworkID) - if err != nil { - return nil - } - - bz, err := sig.MarshalBytes() - if err != nil { - return nil - } - - return bz -} - -func verifyVoteExtSig(signature []byte, message votepersistenceTypes.VoteExtBody, minaKey []byte, reducedRoot string) bool { - if message.ActionsReducedRoot != reducedRoot { - return false - } - - var pubKey keys.PublicKey - if err := pubKey.Unmarshal(minaKey); err != nil { - return false - } - - var sig minasignature.Signature - if err := sig.UnmarshalBytes(signature); err != nil { - return false - } - - msg, err := message.Marshal() - if err != nil { - return false - } - - return pubKey.VerifyMessage(&sig, hex.EncodeToString(msg), NetworkID) -} - -func extractPayload(txs [][]byte) (abcipb.Payload, error) { - - if len(txs) == 0 { - return abcipb.Payload{}, nil - } - - if !bytes.HasPrefix(txs[0], []byte(VoteExtMarker)) { - return abcipb.Payload{}, votepersistenceTypes.ErrVoteExtMarkerNotFound - } - - voteExtensionTx := txs[0][len([]byte(VoteExtMarker)):] - - var pl abcipb.Payload - - err := pl.Unmarshal(voteExtensionTx) - if err != nil { - return abcipb.Payload{}, err - } - return pl, nil -} - -// Use if you need the validator set of block < N where N is the current block number. -func (h *AbciHandler) getValidatorSet(ctx sdk.Context, currentBlockHeight int64) ([]stakingTypes.ValidatorI, error) { - - var valInfo []stakingTypes.ValidatorI - - if ctx.BlockHeight() == currentBlockHeight { - err := h.stakingKeeper.IterateLastValidators(ctx, func(index int64, validator stakingTypes.ValidatorI) (stop bool) { - valInfo = append(valInfo, validator) - return false - }) - - if err != nil { - return nil, err - } - sortValidatorsByPower(valInfo) - - return valInfo, nil - } - - historicalData, err := h.stakingKeeper.GetHistoricalInfo(ctx, currentBlockHeight) - if err != nil { - return nil, err - } - for _, validator := range historicalData.Valset { - valInfo = append(valInfo, validator) - } - - sortValidatorsByPower(valInfo) - - return valInfo, nil -} - -func sortValidatorsByPower(validators []stakingTypes.ValidatorI) { - sort.SliceStable(validators, func(i, j int) bool { - leftPower := validators[i].GetConsensusPower(sdk.DefaultPowerReduction) - rightPower := validators[j].GetConsensusPower(sdk.DefaultPowerReduction) - - if leftPower == rightPower { - leftAddr, err := validators[i].GetConsAddr() - if err != nil { - return false - } - rightAddr, err := validators[j].GetConsAddr() - if err != nil { - return false - } - - return bytes.Compare(leftAddr, rightAddr) == -1 - } - - return leftPower > rightPower - }) -} - -// TODO: Move this helper to mina-signer-go -func (h *AbciHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []stakingTypes.ValidatorI, poseidonHash *poseidon.Poseidon) (*big.Int, error) { - - input := []*big.Int{big.NewInt(0)} - merkleRoot := poseidonHash.Hash(input) - - for _, validator := range valInfo { - input = []*big.Int{} - - consAddr, err := validator.GetConsAddr() - if err != nil { - continue - } - - cosmosValidatorInfo, err := h.stakingKeeper.GetValidatorByConsAddr(ctx, consAddr) - if err != nil { - return nil, err - } - - cosmosValidatorPubKey, err := cosmosValidatorInfo.ConsPubKey() - if err != nil { - return nil, err - } - - minaPubKeyExists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, cosmosValidatorPubKey.Bytes()) - if err != nil { - return nil, err - } - if !minaPubKeyExists { - return nil, err - } - - minaPubKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, cosmosValidatorPubKey.Bytes()) - if err != nil { - return nil, err - } - - var MinaPublicKey keys.PublicKey - err = MinaPublicKey.Unmarshal(minaPubKey) - if err != nil { - return nil, err - } - - input = append(input, MinaPublicKey.X) - if MinaPublicKey.IsOdd { - input = append(input, big.NewInt(1)) - } else { - input = append(input, big.NewInt(0)) - } - power := new(big.Int).SetInt64(validator.GetConsensusPower(sdk.DefaultPowerReduction)) - input = append(input, power) - - hashOfAddr := poseidonHash.Hash(input) - - input = []*big.Int{merkleRoot, hashOfAddr} - - merkleRoot = poseidonHash.Hash(input) - } - - return merkleRoot, nil - -} - -func (h *AbciHandler) checkStakePower(ctx sdk.Context, blockHeight int64, pl abcipb.Payload, body votepersistenceTypes.VoteExtBody) (bool, error) { - var signedStakePower int64 - var currentValidatorStakePower int64 - - valInfoMap := make(map[string]stakingTypes.ValidatorI) - validatorSeen := make(map[string]bool) - - currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) - if err != nil { - return false, err - } - - // Require at least 2/3 signed power to prevent proposer-side signature withholding. - for _, val := range currentValidatorSet { - - consAddr, err := val.GetConsAddr() - if err != nil { - continue - } - - cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, consAddr) - if err != nil { - return false, err - } - - valInfoMap[hex.EncodeToString(cosmosValidatorPubKey)] = val - currentValidatorStakePower += val.GetConsensusPower(sdk.DefaultPowerReduction) - } - - for _, vote := range pl.Votes { - - validatorInfo, ok := valInfoMap[vote.ConsensusPublicKey] - if !ok { - continue - } - - pk, err := hex.DecodeString(vote.ConsensusPublicKey) - if err != nil { - return false, err - } - - if validatorSeen[vote.ConsensusPublicKey] { - continue - } - - validatorSeen[vote.ConsensusPublicKey] = true - - exists, err := h.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, pk) - if err != nil { - return false, err - } - if !exists { - return false, types.ErrValidatorNotRegistered - } - - minaKey, err := h.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, pk) - if err != nil { - return false, err - } - - if !verifyVoteExtSig(vote.VoteExtension, body, minaKey, ActionsReducedRoot) { - return false, votepersistenceTypes.ErrInvalidVoteExtension.Wrap("invalid signature") - } - - signedStakePower += validatorInfo.GetConsensusPower(sdk.DefaultPowerReduction) - - } - if signedStakePower*3 < currentValidatorStakePower*2 { - return false, nil - } - - return true, nil -} - -func (h *AbciHandler) constructVoteExtBody(ctx sdk.Context, blockHeight int64) (votepersistenceTypes.VoteExtBody, error) { - - nextValidatorSet, err := h.getValidatorSet(ctx, blockHeight) - if err != nil { - return votepersistenceTypes.VoteExtBody{}, err - } - - currentBlockInfo, err := h.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-1) - if err != nil { - return votepersistenceTypes.VoteExtBody{}, err - } - - poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) - - nextValidatorSetHash, err := h.calculateValidatorSetRoot(ctx, nextValidatorSet, poseidonHash) - if err != nil { - return votepersistenceTypes.VoteExtBody{}, err - } - if nextValidatorSetHash == nil { - return votepersistenceTypes.VoteExtBody{}, err - } - - return votepersistenceTypes.VoteExtBody{ - NextValidatorSetHash: nextValidatorSetHash.Bytes(), - CurrentStateRoot: currentBlockInfo.Header.AppHash, - CurrentBlockHeight: blockHeight - 1, - ActionsReducedRoot: ActionsReducedRoot, - }, nil -} - -func (h *AbciHandler) getValidatorPublicKey(ctx sdk.Context, validatorAddr []byte) ([]byte, error) { - - cosmosValidatorInfo, err := h.stakingKeeper.GetValidatorByConsAddr(ctx, validatorAddr) - if err != nil { - return nil, err - } - cosmosValidatorPubKey, err := cosmosValidatorInfo.ConsPubKey() - if err != nil { - return nil, err - } - - return cosmosValidatorPubKey.Bytes(), nil -} - -func (h *AbciHandler) constructPayload(ctx sdk.Context, blockHeight int64, voteExtensions []abci.ExtendedVoteInfo) (abcipb.Payload, error) { - - var voteExtsForGivenBlock []*abcipb.Votes - - currentValidatorSetMap := make(map[string]bool) - - currentValidatorSet, err := h.getValidatorSet(ctx, blockHeight-2) - if err != nil { - return abcipb.Payload{}, err - } - - for _, currentValidator := range currentValidatorSet { - - consAddr, err := currentValidator.GetConsAddr() - if err != nil { - continue - } - - currentValidatorSetMap[string(consAddr)] = true - } - - for _, vote := range voteExtensions { - - if !currentValidatorSetMap[string(vote.Validator.Address)] { - continue - } - - if vote.BlockIdFlag != tmproto.BlockIDFlagCommit { - continue - } - - if len(vote.VoteExtension) == 0 { - continue - } - - cosmosValidatorPubKey, err := h.getValidatorPublicKey(ctx, vote.Validator.Address) - if err != nil { - return abcipb.Payload{}, err - } - - voteExtsForGivenBlock = append(voteExtsForGivenBlock, &abcipb.Votes{ - ConsensusPublicKey: hex.EncodeToString(cosmosValidatorPubKey), - VoteExtension: vote.VoteExtension, - }) - } - - if len(voteExtsForGivenBlock) == 0 { - return abcipb.Payload{}, nil - } - - return abcipb.Payload{Height: blockHeight - 1, Votes: voteExtsForGivenBlock}, nil -} diff --git a/scripts/derive_mina_pub.go b/scripts/derive_mina_pub.go deleted file mode 100644 index a7da84ca..00000000 --- a/scripts/derive_mina_pub.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "encoding/base64" - "fmt" - "math/big" - "os" - - "github.com/node101-io/mina-signer-go/keys" -) - -func main() { - if len(os.Args) != 2 { - panic("usage: derive_mina_pub.go ") - } - - privB64 := os.Args[1] - keyBytes, err := base64.StdEncoding.DecodeString(privB64) - if err != nil { - panic(err) - } - - priv := keys.PrivateKey{Value: new(big.Int).SetBytes(keyBytes)} - pub := priv.ToPublicKey() - bz, err := pub.Marshal() - if err != nil { - panic(err) - } - - fmt.Print(base64.StdEncoding.EncodeToString(bz)) -} diff --git a/x/votepersistence/keeper/query_vote_ext_body_by_height.go b/x/votepersistence/keeper/query_vote_ext_body_by_height.go deleted file mode 100644 index b8aea73d..00000000 --- a/x/votepersistence/keeper/query_vote_ext_body_by_height.go +++ /dev/null @@ -1,113 +0,0 @@ -package keeper - -import ( - "context" - "math/big" - - sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/node101-io/mina-signer-go/constants" - "github.com/node101-io/mina-signer-go/field" - "github.com/node101-io/mina-signer-go/keys" - "github.com/node101-io/mina-signer-go/poseidon" - "github.com/node101-io/pulsar-chain/x/votepersistence/types" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -const ActionsReducedRoot string = "pulsar" - -func (q queryServer) VoteExtBodyByHeight(ctx context.Context, req *types.QueryVoteExtBodyByHeightRequest) (*types.VoteExtBody, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "invalid request") - } - - if req.BlockHeight < 4 { - return nil, status.Error(codes.InvalidArgument, "there is no vote extension in blocks smaller than 4") - } - - sdkCtx := sdk.UnwrapSDKContext(ctx) - - if req.BlockHeight >= sdkCtx.BlockHeight() { - return nil, status.Error(codes.InvalidArgument, "no vote extensions in the requested block yet") - } - - if q.k.stakingKeeper == nil || q.k.keyregistryKeeper == nil { - return nil, status.Error(codes.Internal, "vote extension query dependencies are not configured") - } - - return q.constructVoteExtBodyByHeight(ctx, req.BlockHeight) -} - -func (q queryServer) constructVoteExtBodyByHeight(ctx context.Context, blockHeight int64) (*types.VoteExtBody, error) { - currentBlockInfo, err := q.k.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-2) - if err != nil { - return nil, err - } - - nextBlockInfo, err := q.k.stakingKeeper.GetHistoricalInfo(ctx, blockHeight-1) - if err != nil { - return nil, err - } - - nextValidatorSetHash, err := q.calculateValidatorSetRoot(ctx, nextBlockInfo.Valset) - if err != nil { - return nil, err - } - - return &types.VoteExtBody{ - NextValidatorSetHash: nextValidatorSetHash, - CurrentStateRoot: currentBlockInfo.Header.AppHash, - CurrentBlockHeight: blockHeight - 1, - ActionsReducedRoot: ActionsReducedRoot, - }, nil -} - -func (q queryServer) calculateValidatorSetRoot(ctx context.Context, validatorSet []stakingtypes.Validator) ([]byte, error) { - - poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) - merkleRoot := poseidonHash.Hash([]*big.Int{big.NewInt(0)}) - - for _, validator := range validatorSet { - cosmosValidatorPubKey, err := validator.ConsPubKey() - if err != nil { - return nil, status.Error(codes.Internal, "failed to read validator consensus public key") - } - - exists, err := q.k.keyregistryKeeper.ValidatorCosmosToMinaHas(ctx, cosmosValidatorPubKey.Bytes()) - if err != nil { - return nil, status.Error(codes.Internal, "failed to check validator Mina key") - } - if !exists { - return nil, status.Errorf(codes.NotFound, "validator Mina key not found for consensus public key %X", cosmosValidatorPubKey.Bytes()) - } - - minaPubKey, err := q.k.keyregistryKeeper.ValidatorGetCosmosToMina(ctx, cosmosValidatorPubKey.Bytes()) - if err != nil { - return nil, status.Error(codes.Internal, "failed to load validator Mina key") - } - - var minaPublicKey keys.PublicKey - err = minaPublicKey.Unmarshal(minaPubKey) - if err != nil { - return nil, status.Error(codes.Internal, "failed to decode validator Mina public key") - } - - input := []*big.Int{minaPublicKey.X} - if minaPublicKey.IsOdd { - input = append(input, big.NewInt(1)) - } else { - input = append(input, big.NewInt(0)) - } - input = append(input, big.NewInt(validator.ConsensusPower(sdk.DefaultPowerReduction))) - - hashOfValidator := poseidonHash.Hash(input) - merkleRoot = poseidonHash.Hash([]*big.Int{merkleRoot, hashOfValidator}) - } - - if merkleRoot == nil { - return nil, status.Error(codes.Internal, "failed to calculate next validator set hash") - } - - return merkleRoot.Bytes(), nil -} diff --git a/x/votepersistence/keeper/query_vote_ext_body_by_height_test.go b/x/votepersistence/keeper/query_vote_ext_body_by_height_test.go deleted file mode 100644 index b3cb5b20..00000000 --- a/x/votepersistence/keeper/query_vote_ext_body_by_height_test.go +++ /dev/null @@ -1,244 +0,0 @@ -package keeper_test - -import ( - "math/big" - "testing" - - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/node101-io/mina-signer-go/constants" - "github.com/node101-io/mina-signer-go/field" - "github.com/node101-io/mina-signer-go/keys" - "github.com/node101-io/mina-signer-go/poseidon" - keyregistrykeeper "github.com/node101-io/pulsar-chain/x/keyregistry/keeper" - keyregistrytypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" - "github.com/node101-io/pulsar-chain/x/votepersistence/keeper" - "github.com/node101-io/pulsar-chain/x/votepersistence/types" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -var queryMockCosmosSignature = []byte("cosmosSig") -var queryMockMinaSignature = []byte("minaSig") - -func newBondedValidator(t *testing.T, power int64) stakingtypes.Validator { - t.Helper() - - consPubKey := ed25519.GenPrivKey().PubKey() - validator, err := stakingtypes.NewValidator( - sdk.ValAddress(consPubKey.Address()).String(), - consPubKey, - stakingtypes.Description{}, - ) - require.NoError(t, err) - - validator = validator.UpdateStatus(stakingtypes.Bonded) - validator.Tokens = sdk.TokensFromConsensusPower(power, sdk.DefaultPowerReduction) - - return validator -} - -func generateMinaPublicKey(t *testing.T, seed [32]byte) []byte { - t.Helper() - - minaPrivKey := keys.NewPrivateKeyFromBytes(seed) - minaPubKey, err := minaPrivKey.ToPublicKey().Marshal() - require.NoError(t, err) - - return minaPubKey -} - -func registerValidatorKeys(t *testing.T, f *fixture, cosmosPubKey cryptotypes.PubKey, minaPubKey []byte) { - t.Helper() - - ms := keyregistrykeeper.NewMsgServerImpl(f.keyregistryKeeper) - creatorAddr := sdk.AccAddress(cosmosPubKey.Address()) - - _, err := ms.RegisterKeys(f.ctx, &keyregistrytypes.MsgRegisterKeys{ - Creator: creatorAddr.String(), - CosmosSignature: queryMockCosmosSignature, - MinaSignature: queryMockMinaSignature, - CosmosPublicKey: cosmosPubKey.Bytes(), - MinaPublicKey: minaPubKey, - ActorType: keyregistrytypes.ActorType_VALIDATOR, - }) - require.NoError(t, err) -} - -func calculateExpectedValidatorSetRoot(t *testing.T, validatorSet []stakingtypes.Validator, cosmosToMina map[string][]byte) []byte { - t.Helper() - - poseidonHash := poseidon.CreatePoseidon(*field.Fp, constants.PoseidonParamsKimchiFp) - merkleRoot := poseidonHash.Hash([]*big.Int{big.NewInt(0)}) - - for _, validator := range validatorSet { - cosmosValidatorPubKey, err := validator.ConsPubKey() - require.NoError(t, err) - - minaPubKeyBz, ok := cosmosToMina[string(cosmosValidatorPubKey.Bytes())] - require.True(t, ok) - - var minaPubKey keys.PublicKey - require.NoError(t, minaPubKey.Unmarshal(minaPubKeyBz)) - - input := []*big.Int{minaPubKey.X} - if minaPubKey.IsOdd { - input = append(input, big.NewInt(1)) - } else { - input = append(input, big.NewInt(0)) - } - input = append(input, big.NewInt(validator.ConsensusPower(sdk.DefaultPowerReduction))) - - hashOfValidator := poseidonHash.Hash(input) - merkleRoot = poseidonHash.Hash([]*big.Int{merkleRoot, hashOfValidator}) - } - - return merkleRoot.Bytes() -} - -// TestVoteExtBodyByHeightInvalidArgumentFail verifies that VoteExtBodyByHeight -// returns an InvalidArgument error when called with a nil request. -func TestVoteExtBodyByHeightInvalidArgumentFail(t *testing.T) { - f := initFixture(t) - - qs := keeper.NewQueryServerImpl(f.keeper) - params := types.DefaultParams() - require.NoError(t, f.keeper.Params.Set(f.ctx, params)) - - _, err := qs.VoteExtBodyByHeight(f.ctx, nil) - require.Error(t, err) - - st, _ := status.FromError(err) - require.Equal(t, codes.InvalidArgument, st.Code()) -} - -// TestVoteExtBodyByHeightEarlyBlockInvalidArgumentFail verifies that -// VoteExtBodyByHeight rejects requests for block heights smaller than 4. -func TestVoteExtBodyByHeightEarlyBlockInvalidArgumentFail(t *testing.T) { - f := initFixture(t) - - qs := keeper.NewQueryServerImpl(f.keeper) - params := types.DefaultParams() - require.NoError(t, f.keeper.Params.Set(f.ctx, params)) - - _, err := qs.VoteExtBodyByHeight(f.ctx, &types.QueryVoteExtBodyByHeightRequest{ - BlockHeight: 3, - }) - require.Error(t, err) - - st, _ := status.FromError(err) - require.Equal(t, codes.InvalidArgument, st.Code()) -} - -// TestVoteExtBodyByHeightRequestedBlockNotAvailable verifies that -// VoteExtBodyByHeight rejects requests for the current or future block. -func TestVoteExtBodyByHeightRequestedBlockNotAvailable(t *testing.T) { - f := initFixture(t) - ctx := f.ctx.WithBlockHeight(10) - - qs := keeper.NewQueryServerImpl(f.keeper) - params := types.DefaultParams() - require.NoError(t, f.keeper.Params.Set(f.ctx, params)) - - _, err := qs.VoteExtBodyByHeight(ctx, &types.QueryVoteExtBodyByHeightRequest{ - BlockHeight: 10, - }) - require.Error(t, err) - - st, _ := status.FromError(err) - require.Equal(t, codes.InvalidArgument, st.Code()) -} - -// TestVoteExtBodyByHeightSuccess verifies that VoteExtBodyByHeight constructs -// the expected body using real staking historical info and registered validator -// Mina keys. -func TestVoteExtBodyByHeightSuccess(t *testing.T) { - f := initFixture(t) - - validatorOne := newBondedValidator(t, 25) - validatorTwo := newBondedValidator(t, 10) - - consPubKeyOne, err := validatorOne.ConsPubKey() - require.NoError(t, err) - consPubKeyTwo, err := validatorTwo.ConsPubKey() - require.NoError(t, err) - - minaPubKeyOne := generateMinaPublicKey(t, [32]byte{ - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - }) - minaPubKeyTwo := generateMinaPublicKey(t, [32]byte{ - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - }) - - registerValidatorKeys(t, f, consPubKeyOne, minaPubKeyOne) - registerValidatorKeys(t, f, consPubKeyTwo, minaPubKeyTwo) - - require.NoError(t, f.stakingKeeper.SetHistoricalInfo(f.ctx, 6, &stakingtypes.HistoricalInfo{ - Header: tmproto.Header{AppHash: []byte("current-state-root")}, - })) - require.NoError(t, f.stakingKeeper.SetHistoricalInfo(f.ctx, 7, &stakingtypes.HistoricalInfo{ - Valset: []stakingtypes.Validator{validatorOne, validatorTwo}, - })) - - cosmosToMina := map[string][]byte{ - string(consPubKeyOne.Bytes()): minaPubKeyOne, - string(consPubKeyTwo.Bytes()): minaPubKeyTwo, - } - - ctx := f.ctx.WithBlockHeight(10) - qs := keeper.NewQueryServerImpl(f.keeper) - params := types.DefaultParams() - require.NoError(t, f.keeper.Params.Set(f.ctx, params)) - - queryResp, err := qs.VoteExtBodyByHeight(ctx, &types.QueryVoteExtBodyByHeightRequest{ - BlockHeight: 8, - }) - require.NoError(t, err) - require.NotNil(t, queryResp) - - require.Equal(t, &types.VoteExtBody{ - NextValidatorSetHash: calculateExpectedValidatorSetRoot(t, []stakingtypes.Validator{validatorOne, validatorTwo}, cosmosToMina), - CurrentStateRoot: []byte("current-state-root"), - CurrentBlockHeight: 7, - ActionsReducedRoot: keeper.ActionsReducedRoot, - }, queryResp) -} - -// TestVoteExtBodyByHeightValidatorMinaKeyNotFound verifies that -// VoteExtBodyByHeight returns a NotFound error when a validator is missing a -// registered Mina key. -func TestVoteExtBodyByHeightValidatorMinaKeyNotFound(t *testing.T) { - f := initFixture(t) - - validator := newBondedValidator(t, 15) - - require.NoError(t, f.stakingKeeper.SetHistoricalInfo(f.ctx, 6, &stakingtypes.HistoricalInfo{ - Header: tmproto.Header{AppHash: []byte("current-state-root")}, - })) - require.NoError(t, f.stakingKeeper.SetHistoricalInfo(f.ctx, 7, &stakingtypes.HistoricalInfo{ - Valset: []stakingtypes.Validator{validator}, - })) - - ctx := f.ctx.WithBlockHeight(10) - qs := keeper.NewQueryServerImpl(f.keeper) - params := types.DefaultParams() - require.NoError(t, f.keeper.Params.Set(f.ctx, params)) - - _, err := qs.VoteExtBodyByHeight(ctx, &types.QueryVoteExtBodyByHeightRequest{ - BlockHeight: 8, - }) - require.Error(t, err) - - st, _ := status.FromError(err) - require.Equal(t, codes.NotFound, st.Code()) -} From 79bb691e3fb80dcf1accf07ee701974d6ee0c79f Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 1 Jun 2026 17:04:35 +0300 Subject: [PATCH 56/63] fix: marshall mina addresses properly --- x/bridge/keeper/helpers_push_new_actions.go | 11 ++++++----- x/bridge/keeper/mina_archive.go | 11 +++++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/x/bridge/keeper/helpers_push_new_actions.go b/x/bridge/keeper/helpers_push_new_actions.go index 839ce56d..d6b98859 100644 --- a/x/bridge/keeper/helpers_push_new_actions.go +++ b/x/bridge/keeper/helpers_push_new_actions.go @@ -33,7 +33,7 @@ func (k *Keeper) isValid(ctx context.Context, act *FetchedAction) (bool, error) func (k *Keeper) isValidDeposit(ctx context.Context, act *FetchedAction) (bool, error) { - exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, []byte(act.FeePayer)) + exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, act.FeePayer) if err != nil { return false, err } @@ -44,7 +44,8 @@ func (k *Keeper) isValidDeposit(ctx context.Context, act *FetchedAction) (bool, } func (k *Keeper) isValidWithdrawal(ctx context.Context, act *FetchedAction) (bool, error) { - exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, []byte(act.FeePayer)) + + exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, act.FeePayer) if err != nil { return false, err } @@ -52,7 +53,7 @@ func (k *Keeper) isValidWithdrawal(ctx context.Context, act *FetchedAction) (boo return false, nil } - cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) + cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, act.FeePayer) if err != nil { return false, err } @@ -87,7 +88,7 @@ func (k *Keeper) apply(ctx context.Context, act *FetchedAction) error { func (k *Keeper) applyDeposit(ctx context.Context, act *FetchedAction) error { - cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) + cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, act.FeePayer) if err != nil { return err } @@ -108,7 +109,7 @@ func (k *Keeper) applyDeposit(ctx context.Context, act *FetchedAction) error { func (k *Keeper) applyWithdrawal(ctx context.Context, act *FetchedAction) error { - cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, []byte(act.FeePayer)) + cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, act.FeePayer) if err != nil { return err } diff --git a/x/bridge/keeper/mina_archive.go b/x/bridge/keeper/mina_archive.go index b639b5c5..ba09dd16 100644 --- a/x/bridge/keeper/mina_archive.go +++ b/x/bridge/keeper/mina_archive.go @@ -7,6 +7,8 @@ import ( "io" "net/http" "strconv" + + "github.com/node101-io/mina-signer-go/address" ) var ArchiveGraphQLEndpoint = "https://devnet-archive-node-api.gcp.o1test.net" @@ -27,7 +29,7 @@ type GraphQLRequest struct { type FetchedAction struct { BlockHeight int - FeePayer string + FeePayer []byte actionType int Amount int64 } @@ -244,9 +246,14 @@ func fetchedActionFromActionData(blockHeight int, feePayer string, data []string return nil, nil } + minaAddr, err := address.NewAddress(feePayer).Marshal() + if err != nil { + return nil, err + } + return &FetchedAction{ BlockHeight: blockHeight, - FeePayer: feePayer, + FeePayer: minaAddr, actionType: actionType, Amount: amount, }, nil From 9be7917ef71be840cc7fbeb64df6d546e76325fa Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 1 Jun 2026 17:19:50 +0300 Subject: [PATCH 57/63] fix: build action type with proto --- proto/pulsarchain/bridge/v1/action.proto | 18 + x/bridge/keeper/helpers_push_new_actions.go | 30 +- x/bridge/keeper/mina_archive.go | 35 +- x/bridge/keeper/mina_archive_test.go | 2 +- x/bridge/types/action.pb.go | 461 ++++++++++++++++++++ 5 files changed, 505 insertions(+), 41 deletions(-) create mode 100644 proto/pulsarchain/bridge/v1/action.proto create mode 100644 x/bridge/types/action.pb.go diff --git a/proto/pulsarchain/bridge/v1/action.proto b/proto/pulsarchain/bridge/v1/action.proto new file mode 100644 index 00000000..9bf40176 --- /dev/null +++ b/proto/pulsarchain/bridge/v1/action.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; +package pulsarchain.bridge.v1; + +option go_package = "github.com/node101-io/pulsar-chain/x/bridge/types"; + +enum ActionType { + UNSPECIFIED = 0; + DEPOSIT = 1; + WITHDRAW = 2; +} + + +message Action { + int64 block_height = 1; + bytes fee_payer = 2; + ActionType action_type = 3; + int64 amount = 4; +} diff --git a/x/bridge/keeper/helpers_push_new_actions.go b/x/bridge/keeper/helpers_push_new_actions.go index d6b98859..679e41ba 100644 --- a/x/bridge/keeper/helpers_push_new_actions.go +++ b/x/bridge/keeper/helpers_push_new_actions.go @@ -11,27 +11,21 @@ import ( keyregistryTypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" ) -const ( - UNSPECIFIED = iota - DEPOSIT - WITHDRAW -) - -func (k *Keeper) isValid(ctx context.Context, act *FetchedAction) (bool, error) { +func (k *Keeper) isValid(ctx context.Context, act *types.Action) (bool, error) { if k.keyRegistryKeeper == nil { return false, types.ErrKeyRegistryKeeperNotConfigured } - switch act.actionType { - case DEPOSIT: + switch act.ActionType { + case types.ActionType_DEPOSIT: return k.isValidDeposit(ctx, act) - case WITHDRAW: + case types.ActionType_WITHDRAW: return k.isValidWithdrawal(ctx, act) default: return false, types.ErrUnspecified } } -func (k *Keeper) isValidDeposit(ctx context.Context, act *FetchedAction) (bool, error) { +func (k *Keeper) isValidDeposit(ctx context.Context, act *types.Action) (bool, error) { exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, act.FeePayer) if err != nil { @@ -43,7 +37,7 @@ func (k *Keeper) isValidDeposit(ctx context.Context, act *FetchedAction) (bool, return true, nil } -func (k *Keeper) isValidWithdrawal(ctx context.Context, act *FetchedAction) (bool, error) { +func (k *Keeper) isValidWithdrawal(ctx context.Context, act *types.Action) (bool, error) { exists, err := k.keyRegistryKeeper.UserMinaToCosmosHas(ctx, act.FeePayer) if err != nil { @@ -70,23 +64,23 @@ func (k *Keeper) isValidWithdrawal(ctx context.Context, act *FetchedAction) (boo return true, nil } -func (k *Keeper) apply(ctx context.Context, act *FetchedAction) error { +func (k *Keeper) apply(ctx context.Context, act *types.Action) error { if k.bankKeeper == nil { return types.ErrBankKeeperNotConfigured } - switch act.actionType { - case DEPOSIT: + switch act.ActionType { + case types.ActionType_DEPOSIT: return k.applyDeposit(ctx, act) - case WITHDRAW: + case types.ActionType_WITHDRAW: return k.applyWithdrawal(ctx, act) default: return types.ErrUnspecified } } -func (k *Keeper) applyDeposit(ctx context.Context, act *FetchedAction) error { +func (k *Keeper) applyDeposit(ctx context.Context, act *types.Action) error { cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, act.FeePayer) if err != nil { @@ -107,7 +101,7 @@ func (k *Keeper) applyDeposit(ctx context.Context, act *FetchedAction) error { return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, coins) } -func (k *Keeper) applyWithdrawal(ctx context.Context, act *FetchedAction) error { +func (k *Keeper) applyWithdrawal(ctx context.Context, act *types.Action) error { cosmosPubKey, err := k.keyRegistryKeeper.UserGetMinaToCosmos(ctx, act.FeePayer) if err != nil { diff --git a/x/bridge/keeper/mina_archive.go b/x/bridge/keeper/mina_archive.go index ba09dd16..2c002ad1 100644 --- a/x/bridge/keeper/mina_archive.go +++ b/x/bridge/keeper/mina_archive.go @@ -9,6 +9,7 @@ import ( "strconv" "github.com/node101-io/mina-signer-go/address" + "github.com/node101-io/pulsar-chain/x/bridge/types" ) var ArchiveGraphQLEndpoint = "https://devnet-archive-node-api.gcp.o1test.net" @@ -27,13 +28,6 @@ type GraphQLRequest struct { Query string `json:"query"` } -type FetchedAction struct { - BlockHeight int - FeePayer []byte - actionType int - Amount int64 -} - const ( pulsarActionTypeIndex = 0 pulsarActionAmountIndex = 3 @@ -133,7 +127,7 @@ query GetMinaBlockHeights { return int64(result.Data.NetworkState.MaxBlockHeight.PendingMaxBlockHeight), nil } -func fetchActions(contractAddress string, start, end int64) ([]FetchedAction, error) { +func fetchActions(contractAddress string, start, end int64) ([]types.Action, error) { blockLimit := int(end - start + 1) if blockLimit < 1 { blockLimit = 1 @@ -214,7 +208,7 @@ query ($actionInput: ActionFilterOptionsInput!, $blockQuery: BlockQueryInput!, $ } } - actions := make([]FetchedAction, 0) + actions := make([]types.Action, 0) for _, block := range result.Data.Actions { for _, actionData := range block.ActionData { fetchedAction, err := fetchedActionFromActionData( @@ -236,13 +230,13 @@ query ($actionInput: ActionFilterOptionsInput!, $blockQuery: BlockQueryInput!, $ return actions, nil } -func fetchedActionFromActionData(blockHeight int, feePayer string, data []string) (*FetchedAction, error) { +func fetchedActionFromActionData(blockHeight int, feePayer string, data []string) (*types.Action, error) { actionType, amount, err := contractActionTypeAndAmountFromActionData(data) if err != nil { return nil, err } - if actionType == UNSPECIFIED { + if actionType == types.ActionType_UNSPECIFIED { return nil, nil } @@ -251,15 +245,15 @@ func fetchedActionFromActionData(blockHeight int, feePayer string, data []string return nil, err } - return &FetchedAction{ - BlockHeight: blockHeight, + return &types.Action{ + BlockHeight: int64(blockHeight), FeePayer: minaAddr, - actionType: actionType, + ActionType: actionType, Amount: amount, }, nil } -func contractActionTypeAndAmountFromActionData(data []string) (int, int64, error) { +func contractActionTypeAndAmountFromActionData(data []string) (types.ActionType, int64, error) { if len(data) < pulsarActionFieldCount { return 0, 0, fmt.Errorf("invalid action data length: got %d fields, expected at least %d", len(data), pulsarActionFieldCount) } @@ -278,12 +272,9 @@ func contractActionTypeAndAmountFromActionData(data []string) (int, int64, error return 0, 0, fmt.Errorf("invalid non-positive action amount: %d", amount) } - switch actionType { - case UNSPECIFIED: - return actionType, 0, nil - case DEPOSIT, WITHDRAW: - return actionType, amount, nil - default: - return UNSPECIFIED, 0, nil + if actionType == int(types.ActionType_UNSPECIFIED) { + return types.ActionType_UNSPECIFIED, 0, nil } + + return types.ActionType(actionType), amount, nil } diff --git a/x/bridge/keeper/mina_archive_test.go b/x/bridge/keeper/mina_archive_test.go index 89b98c2a..4482e624 100644 --- a/x/bridge/keeper/mina_archive_test.go +++ b/x/bridge/keeper/mina_archive_test.go @@ -28,7 +28,7 @@ func TestFetchActions(t *testing.T) { for _, act := range actions { - fmt.Println(act.actionType, act.Amount, act.BlockHeight, act.FeePayer) + fmt.Println(act.ActionType, act.Amount, act.BlockHeight, act.FeePayer) } diff --git a/x/bridge/types/action.pb.go b/x/bridge/types/action.pb.go new file mode 100644 index 00000000..96ff76cf --- /dev/null +++ b/x/bridge/types/action.pb.go @@ -0,0 +1,461 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: pulsarchain/bridge/v1/action.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type ActionType int32 + +const ( + ActionType_UNSPECIFIED ActionType = 0 + ActionType_DEPOSIT ActionType = 1 + ActionType_WITHDRAW ActionType = 2 +) + +var ActionType_name = map[int32]string{ + 0: "UNSPECIFIED", + 1: "DEPOSIT", + 2: "WITHDRAW", +} + +var ActionType_value = map[string]int32{ + "UNSPECIFIED": 0, + "DEPOSIT": 1, + "WITHDRAW": 2, +} + +func (x ActionType) String() string { + return proto.EnumName(ActionType_name, int32(x)) +} + +func (ActionType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_4c3d593beb882b0e, []int{0} +} + +type Action struct { + BlockHeight int64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` + FeePayer []byte `protobuf:"bytes,2,opt,name=fee_payer,json=feePayer,proto3" json:"fee_payer,omitempty"` + ActionType ActionType `protobuf:"varint,3,opt,name=action_type,json=actionType,proto3,enum=pulsarchain.bridge.v1.ActionType" json:"action_type,omitempty"` + Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (m *Action) Reset() { *m = Action{} } +func (m *Action) String() string { return proto.CompactTextString(m) } +func (*Action) ProtoMessage() {} +func (*Action) Descriptor() ([]byte, []int) { + return fileDescriptor_4c3d593beb882b0e, []int{0} +} +func (m *Action) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Action) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Action.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 *Action) XXX_Merge(src proto.Message) { + xxx_messageInfo_Action.Merge(m, src) +} +func (m *Action) XXX_Size() int { + return m.Size() +} +func (m *Action) XXX_DiscardUnknown() { + xxx_messageInfo_Action.DiscardUnknown(m) +} + +var xxx_messageInfo_Action proto.InternalMessageInfo + +func (m *Action) GetBlockHeight() int64 { + if m != nil { + return m.BlockHeight + } + return 0 +} + +func (m *Action) GetFeePayer() []byte { + if m != nil { + return m.FeePayer + } + return nil +} + +func (m *Action) GetActionType() ActionType { + if m != nil { + return m.ActionType + } + return ActionType_UNSPECIFIED +} + +func (m *Action) GetAmount() int64 { + if m != nil { + return m.Amount + } + return 0 +} + +func init() { + proto.RegisterEnum("pulsarchain.bridge.v1.ActionType", ActionType_name, ActionType_value) + proto.RegisterType((*Action)(nil), "pulsarchain.bridge.v1.Action") +} + +func init() { + proto.RegisterFile("pulsarchain/bridge/v1/action.proto", fileDescriptor_4c3d593beb882b0e) +} + +var fileDescriptor_4c3d593beb882b0e = []byte{ + // 303 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2a, 0x28, 0xcd, 0x29, + 0x4e, 0x2c, 0x4a, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x4f, 0x2a, 0xca, 0x4c, 0x49, 0x4f, 0xd5, 0x2f, + 0x33, 0xd4, 0x4f, 0x4c, 0x2e, 0xc9, 0xcc, 0xcf, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, + 0x45, 0x52, 0xa3, 0x07, 0x51, 0xa3, 0x57, 0x66, 0xa8, 0xb4, 0x84, 0x91, 0x8b, 0xcd, 0x11, 0xac, + 0x4e, 0x48, 0x91, 0x8b, 0x27, 0x29, 0x27, 0x3f, 0x39, 0x3b, 0x3e, 0x23, 0x35, 0x33, 0x3d, 0xa3, + 0x44, 0x82, 0x51, 0x81, 0x51, 0x83, 0x39, 0x88, 0x1b, 0x2c, 0xe6, 0x01, 0x16, 0x12, 0x92, 0xe6, + 0xe2, 0x4c, 0x4b, 0x4d, 0x8d, 0x2f, 0x48, 0xac, 0x4c, 0x2d, 0x92, 0x60, 0x52, 0x60, 0xd4, 0xe0, + 0x09, 0xe2, 0x48, 0x4b, 0x4d, 0x0d, 0x00, 0xf1, 0x85, 0x9c, 0xb8, 0xb8, 0x21, 0x36, 0xc6, 0x97, + 0x54, 0x16, 0xa4, 0x4a, 0x30, 0x2b, 0x30, 0x6a, 0xf0, 0x19, 0x29, 0xea, 0x61, 0xb5, 0x57, 0x0f, + 0x62, 0x67, 0x48, 0x65, 0x41, 0x6a, 0x10, 0x57, 0x22, 0x9c, 0x2d, 0x24, 0xc6, 0xc5, 0x96, 0x98, + 0x9b, 0x5f, 0x9a, 0x57, 0x22, 0xc1, 0x02, 0xb6, 0x1d, 0xca, 0xd3, 0xb2, 0xe0, 0xe2, 0x42, 0xe8, + 0x10, 0xe2, 0xe7, 0xe2, 0x0e, 0xf5, 0x0b, 0x0e, 0x70, 0x75, 0xf6, 0x74, 0xf3, 0x74, 0x75, 0x11, + 0x60, 0x10, 0xe2, 0xe6, 0x62, 0x77, 0x71, 0x0d, 0xf0, 0x0f, 0xf6, 0x0c, 0x11, 0x60, 0x14, 0xe2, + 0xe1, 0xe2, 0x08, 0xf7, 0x0c, 0xf1, 0x70, 0x09, 0x72, 0x0c, 0x17, 0x60, 0x72, 0xf2, 0x3e, 0xf1, + 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, + 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xc3, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, + 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xbc, 0xfc, 0x94, 0x54, 0x43, 0x03, 0x43, 0xdd, 0xcc, 0x7c, 0x7d, + 0x88, 0x7b, 0x75, 0x21, 0x81, 0x59, 0x01, 0x0b, 0x4e, 0x90, 0x97, 0x8a, 0x93, 0xd8, 0xc0, 0x61, + 0x69, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xf9, 0x2a, 0xe0, 0xc0, 0x71, 0x01, 0x00, 0x00, +} + +func (m *Action) 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 *Action) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Action) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Amount != 0 { + i = encodeVarintAction(dAtA, i, uint64(m.Amount)) + i-- + dAtA[i] = 0x20 + } + if m.ActionType != 0 { + i = encodeVarintAction(dAtA, i, uint64(m.ActionType)) + i-- + dAtA[i] = 0x18 + } + if len(m.FeePayer) > 0 { + i -= len(m.FeePayer) + copy(dAtA[i:], m.FeePayer) + i = encodeVarintAction(dAtA, i, uint64(len(m.FeePayer))) + i-- + dAtA[i] = 0x12 + } + if m.BlockHeight != 0 { + i = encodeVarintAction(dAtA, i, uint64(m.BlockHeight)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintAction(dAtA []byte, offset int, v uint64) int { + offset -= sovAction(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Action) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BlockHeight != 0 { + n += 1 + sovAction(uint64(m.BlockHeight)) + } + l = len(m.FeePayer) + if l > 0 { + n += 1 + l + sovAction(uint64(l)) + } + if m.ActionType != 0 { + n += 1 + sovAction(uint64(m.ActionType)) + } + if m.Amount != 0 { + n += 1 + sovAction(uint64(m.Amount)) + } + return n +} + +func sovAction(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAction(x uint64) (n int) { + return sovAction(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Action) 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 ErrIntOverflowAction + } + 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: Action: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Action: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockHeight", wireType) + } + m.BlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAction + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeePayer", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAction + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthAction + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthAction + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FeePayer = append(m.FeePayer[:0], dAtA[iNdEx:postIndex]...) + if m.FeePayer == nil { + m.FeePayer = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ActionType", wireType) + } + m.ActionType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAction + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ActionType |= ActionType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + m.Amount = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAction + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Amount |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipAction(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAction + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAction(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAction + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAction + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAction + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthAction + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAction + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAction + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAction = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAction = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAction = fmt.Errorf("proto: unexpected end of group") +) From 1c7f49bb6b57bb1e422055e99b65aa2abdfce8d4 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 1 Jun 2026 17:40:31 +0300 Subject: [PATCH 58/63] feat: store merkle list in the bridge keeper --- x/bridge/keeper/keeper.go | 6 +++++- x/bridge/keeper/keeper_test.go | 7 +++++++ x/bridge/module/depinject.go | 8 ++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/x/bridge/keeper/keeper.go b/x/bridge/keeper/keeper.go index 34f00a69..06964811 100644 --- a/x/bridge/keeper/keeper.go +++ b/x/bridge/keeper/keeper.go @@ -8,7 +8,7 @@ import ( "cosmossdk.io/core/address" corestore "cosmossdk.io/core/store" "github.com/cosmos/cosmos-sdk/codec" - + minasignergo "github.com/node101-io/mina-signer-go/merklelist" "github.com/node101-io/pulsar-chain/x/bridge/types" ) @@ -26,6 +26,8 @@ type Keeper struct { Params collections.Item[types.Params] BridgeState collections.Item[types.BridgeState] + MerkleList *minasignergo.MerkleList + bankKeeper types.BankKeeper keyRegistryKeeper types.KeyregistryKeeper } @@ -37,6 +39,7 @@ func NewKeeper( authority []byte, bankKeeper types.BankKeeper, keyRegistryKeeper types.KeyregistryKeeper, + merkleList *minasignergo.MerkleList, ) Keeper { if _, err := addressCodec.BytesToString(authority); err != nil { panic(fmt.Sprintf("invalid authority address %s: %s", authority, err)) @@ -59,6 +62,7 @@ func NewKeeper( ), bankKeeper: bankKeeper, keyRegistryKeeper: keyRegistryKeeper, + MerkleList: merkleList, } schema, err := sb.Build() diff --git a/x/bridge/keeper/keeper_test.go b/x/bridge/keeper/keeper_test.go index 06bca960..5cd31e1f 100644 --- a/x/bridge/keeper/keeper_test.go +++ b/x/bridge/keeper/keeper_test.go @@ -13,6 +13,7 @@ import ( moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + minasignergo "github.com/node101-io/mina-signer-go/merklelist" "github.com/node101-io/pulsar-chain/x/bridge/keeper" module "github.com/node101-io/pulsar-chain/x/bridge/module" "github.com/node101-io/pulsar-chain/x/bridge/types" @@ -36,6 +37,11 @@ func initFixture(t *testing.T) *fixture { authority := authtypes.NewModuleAddress(types.GovModuleName) + merkleList, err := minasignergo.NewMerkleList("") + if err != nil { + t.Fatal("failed to create merkle list %v", err) + } + k := keeper.NewKeeper( storeService, encCfg.Codec, @@ -43,6 +49,7 @@ func initFixture(t *testing.T) *fixture { authority, nil, nil, + merkleList, ) // Initialize params diff --git a/x/bridge/module/depinject.go b/x/bridge/module/depinject.go index d0c982c1..22102404 100644 --- a/x/bridge/module/depinject.go +++ b/x/bridge/module/depinject.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + minasignergo "github.com/node101-io/mina-signer-go/merklelist" "github.com/node101-io/pulsar-chain/x/bridge/keeper" "github.com/node101-io/pulsar-chain/x/bridge/types" ) @@ -51,6 +52,12 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { if in.Config.Authority != "" { authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) } + + merklelist, err := minasignergo.NewMerkleList("") + if err != nil { + return ModuleOutputs{} + } + k := keeper.NewKeeper( in.StoreService, in.Cdc, @@ -58,6 +65,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { authority, in.BankKeeper, in.KeyregistryKeeper, + merklelist, ) m := NewAppModule(in.Cdc, k, in.AuthKeeper, in.BankKeeper) From 262b077d8bb2800c7325c3c9976f950fcba0e66f Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 1 Jun 2026 17:41:23 +0300 Subject: [PATCH 59/63] feat: implement actions reduced root using mina-signer-go --- .../keeper/msg_server_push_new_actions.go | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/x/bridge/keeper/msg_server_push_new_actions.go b/x/bridge/keeper/msg_server_push_new_actions.go index 027d9770..dfc4b8ae 100644 --- a/x/bridge/keeper/msg_server_push_new_actions.go +++ b/x/bridge/keeper/msg_server_push_new_actions.go @@ -42,13 +42,24 @@ func (k msgServer) PushNewActions(ctx context.Context, msg *types.MsgPushNewActi if err := k.apply(ctx, &act); err != nil { return nil, err } - } - if err := k.Keeper.setBridgeState(ctx, types.BridgeState{ - LatestFetchedMinaHeight: msg.MinaBlockHeight, - ActionsReducedRoot: []byte(""), - }); err != nil { - return nil, err + marshalledAction, err := act.Marshal() + if err != nil { + return nil, err + } + + err = k.Keeper.MerkleList.Append(marshalledAction) + if err != nil { + return nil, err + } + + if err := k.Keeper.setBridgeState(ctx, types.BridgeState{ + LatestFetchedMinaHeight: msg.MinaBlockHeight, + ActionsReducedRoot: k.Keeper.MerkleList.Root(), + }); err != nil { + return nil, err + } + } return &types.MsgPushNewActionsResponse{}, nil From 6c5f8baf39d99bdbf5fd1375575e7355b2c8e1fe Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 1 Jun 2026 17:45:06 +0300 Subject: [PATCH 60/63] chore: set a prefix for merkle list --- x/bridge/keeper/keeper.go | 1 + x/bridge/keeper/keeper_test.go | 2 +- x/bridge/module/depinject.go | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x/bridge/keeper/keeper.go b/x/bridge/keeper/keeper.go index 06964811..16715a52 100644 --- a/x/bridge/keeper/keeper.go +++ b/x/bridge/keeper/keeper.go @@ -13,6 +13,7 @@ import ( ) const BridgeStateItemName string = "bridge_state" +const MerkleListPrefix = "" type Keeper struct { storeService corestore.KVStoreService diff --git a/x/bridge/keeper/keeper_test.go b/x/bridge/keeper/keeper_test.go index 5cd31e1f..bc9752e6 100644 --- a/x/bridge/keeper/keeper_test.go +++ b/x/bridge/keeper/keeper_test.go @@ -37,7 +37,7 @@ func initFixture(t *testing.T) *fixture { authority := authtypes.NewModuleAddress(types.GovModuleName) - merkleList, err := minasignergo.NewMerkleList("") + merkleList, err := minasignergo.NewMerkleList(keeper.MerkleListPrefix) if err != nil { t.Fatal("failed to create merkle list %v", err) } diff --git a/x/bridge/module/depinject.go b/x/bridge/module/depinject.go index 22102404..c4e0e59f 100644 --- a/x/bridge/module/depinject.go +++ b/x/bridge/module/depinject.go @@ -53,7 +53,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) } - merklelist, err := minasignergo.NewMerkleList("") + merklelist, err := minasignergo.NewMerkleList(keeper.MerkleListPrefix) if err != nil { return ModuleOutputs{} } From 45a57a038c400a992d6f1bc31154399c836742ec Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 1 Jun 2026 20:05:14 +0300 Subject: [PATCH 61/63] fix: update mina-signer-go and remove merkle list from keeper --- abci/validator_set.go | 5 +---- go.mod | 2 +- go.sum | 2 ++ x/bridge/keeper/keeper.go | 6 ----- x/bridge/keeper/keeper_test.go | 7 ------ .../keeper/msg_server_push_new_actions.go | 22 +++++-------------- x/bridge/module/depinject.go | 7 ------ x/bridge/types/genesis.go | 4 +++- x/bridge/types/types.go | 2 ++ 9 files changed, 15 insertions(+), 42 deletions(-) diff --git a/abci/validator_set.go b/abci/validator_set.go index d38196ba..cf7eb3f8 100644 --- a/abci/validator_set.go +++ b/abci/validator_set.go @@ -92,10 +92,7 @@ func (h *ABCIHandler) calculateValidatorSetRoot(ctx sdk.Context, valInfo []staki return nil, ErrValidatorSetRootHashFailed } - validatorRoot, err := merklelist.NewMerkleList(ValidatorSetMerklePrefix) - if err != nil { - return nil, fmt.Errorf("%w: %v", ErrValidatorSetRootHashFailed, err) - } + validatorRoot := merklelist.NewMerkleList(ValidatorSetMerklePrefix) for _, validator := range valInfo { consAddr, err := validator.GetConsAddr() diff --git a/go.mod b/go.mod index ce73609e..dd5a1f1f 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/golang/protobuf v1.5.4 github.com/gorilla/mux v1.8.1 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/node101-io/mina-signer-go v0.0.0-20260528161125-58c8e2225973 + github.com/node101-io/mina-signer-go v0.0.0-20260601165332-9dc4888e6819 github.com/spf13/cast v1.10.0 github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 diff --git a/go.sum b/go.sum index a546db23..f44c2ca3 100644 --- a/go.sum +++ b/go.sum @@ -1674,6 +1674,8 @@ github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= github.com/node101-io/mina-signer-go v0.0.0-20260528161125-58c8e2225973 h1:BcjpAAukbhts/ttAtpzof+Ek91D7Kc5wQ2txPbhZOMI= github.com/node101-io/mina-signer-go v0.0.0-20260528161125-58c8e2225973/go.mod h1:vGZaN+qwZwJzSm5WQ4hTs95ULhysLLhz7kV+SLj4Abc= +github.com/node101-io/mina-signer-go v0.0.0-20260601165332-9dc4888e6819 h1:PYnyy92xzQ8oNjsydAenjPURHvOcTu6lsPiJ0iFYCoI= +github.com/node101-io/mina-signer-go v0.0.0-20260601165332-9dc4888e6819/go.mod h1:vGZaN+qwZwJzSm5WQ4hTs95ULhysLLhz7kV+SLj4Abc= github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= diff --git a/x/bridge/keeper/keeper.go b/x/bridge/keeper/keeper.go index 16715a52..459402e2 100644 --- a/x/bridge/keeper/keeper.go +++ b/x/bridge/keeper/keeper.go @@ -8,12 +8,10 @@ import ( "cosmossdk.io/core/address" corestore "cosmossdk.io/core/store" "github.com/cosmos/cosmos-sdk/codec" - minasignergo "github.com/node101-io/mina-signer-go/merklelist" "github.com/node101-io/pulsar-chain/x/bridge/types" ) const BridgeStateItemName string = "bridge_state" -const MerkleListPrefix = "" type Keeper struct { storeService corestore.KVStoreService @@ -27,8 +25,6 @@ type Keeper struct { Params collections.Item[types.Params] BridgeState collections.Item[types.BridgeState] - MerkleList *minasignergo.MerkleList - bankKeeper types.BankKeeper keyRegistryKeeper types.KeyregistryKeeper } @@ -40,7 +36,6 @@ func NewKeeper( authority []byte, bankKeeper types.BankKeeper, keyRegistryKeeper types.KeyregistryKeeper, - merkleList *minasignergo.MerkleList, ) Keeper { if _, err := addressCodec.BytesToString(authority); err != nil { panic(fmt.Sprintf("invalid authority address %s: %s", authority, err)) @@ -63,7 +58,6 @@ func NewKeeper( ), bankKeeper: bankKeeper, keyRegistryKeeper: keyRegistryKeeper, - MerkleList: merkleList, } schema, err := sb.Build() diff --git a/x/bridge/keeper/keeper_test.go b/x/bridge/keeper/keeper_test.go index bc9752e6..06bca960 100644 --- a/x/bridge/keeper/keeper_test.go +++ b/x/bridge/keeper/keeper_test.go @@ -13,7 +13,6 @@ import ( moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - minasignergo "github.com/node101-io/mina-signer-go/merklelist" "github.com/node101-io/pulsar-chain/x/bridge/keeper" module "github.com/node101-io/pulsar-chain/x/bridge/module" "github.com/node101-io/pulsar-chain/x/bridge/types" @@ -37,11 +36,6 @@ func initFixture(t *testing.T) *fixture { authority := authtypes.NewModuleAddress(types.GovModuleName) - merkleList, err := minasignergo.NewMerkleList(keeper.MerkleListPrefix) - if err != nil { - t.Fatal("failed to create merkle list %v", err) - } - k := keeper.NewKeeper( storeService, encCfg.Codec, @@ -49,7 +43,6 @@ func initFixture(t *testing.T) *fixture { authority, nil, nil, - merkleList, ) // Initialize params diff --git a/x/bridge/keeper/msg_server_push_new_actions.go b/x/bridge/keeper/msg_server_push_new_actions.go index dfc4b8ae..c68ba4d9 100644 --- a/x/bridge/keeper/msg_server_push_new_actions.go +++ b/x/bridge/keeper/msg_server_push_new_actions.go @@ -43,23 +43,13 @@ func (k msgServer) PushNewActions(ctx context.Context, msg *types.MsgPushNewActi return nil, err } - marshalledAction, err := act.Marshal() - if err != nil { - return nil, err - } - - err = k.Keeper.MerkleList.Append(marshalledAction) - if err != nil { - return nil, err - } - - if err := k.Keeper.setBridgeState(ctx, types.BridgeState{ - LatestFetchedMinaHeight: msg.MinaBlockHeight, - ActionsReducedRoot: k.Keeper.MerkleList.Root(), - }); err != nil { - return nil, err - } + } + if err := k.Keeper.setBridgeState(ctx, types.BridgeState{ + LatestFetchedMinaHeight: msg.MinaBlockHeight, + ActionsReducedRoot: []byte(""), + }); err != nil { + return nil, err } return &types.MsgPushNewActionsResponse{}, nil diff --git a/x/bridge/module/depinject.go b/x/bridge/module/depinject.go index c4e0e59f..a27a4e8a 100644 --- a/x/bridge/module/depinject.go +++ b/x/bridge/module/depinject.go @@ -9,7 +9,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - minasignergo "github.com/node101-io/mina-signer-go/merklelist" "github.com/node101-io/pulsar-chain/x/bridge/keeper" "github.com/node101-io/pulsar-chain/x/bridge/types" ) @@ -53,11 +52,6 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) } - merklelist, err := minasignergo.NewMerkleList(keeper.MerkleListPrefix) - if err != nil { - return ModuleOutputs{} - } - k := keeper.NewKeeper( in.StoreService, in.Cdc, @@ -65,7 +59,6 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { authority, in.BankKeeper, in.KeyregistryKeeper, - merklelist, ) m := NewAppModule(in.Cdc, k, in.AuthKeeper, in.BankKeeper) diff --git a/x/bridge/types/genesis.go b/x/bridge/types/genesis.go index be6e2eea..aa1dd125 100644 --- a/x/bridge/types/genesis.go +++ b/x/bridge/types/genesis.go @@ -1,5 +1,7 @@ package types +import minasignergo "github.com/node101-io/mina-signer-go/merklelist" + // DefaultGenesis returns the default genesis state func DefaultGenesis() *GenesisState { return &GenesisState{ @@ -18,6 +20,6 @@ func DefaultBridgeState() BridgeState { return BridgeState{ LatestFetchedMinaHeight: 0, - ActionsReducedRoot: nil, + ActionsReducedRoot: minasignergo.NewMerkleList(MerkleListPrefix).Root(), } } diff --git a/x/bridge/types/types.go b/x/bridge/types/types.go index 631be69a..0d3893a2 100644 --- a/x/bridge/types/types.go +++ b/x/bridge/types/types.go @@ -3,3 +3,5 @@ package types const MINA_HARDFINALITY_BLOCK_DURATION int64 = 32 const Denom string = "pMina" const ContractAddress string = "B62qmxfmpgjKrHp31TDzDsSGpNhBEK3To1gVxMGPyBD9BZQi2ctexm4" + +const MerkleListPrefix = "" From 38508e03f3d239b4b10dad62c044912c5c9c5d6f Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 1 Jun 2026 20:19:57 +0300 Subject: [PATCH 62/63] fix: use the NewMerkleListFromRoot to build the actions root --- x/bridge/keeper/msg_server_push_new_actions.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/x/bridge/keeper/msg_server_push_new_actions.go b/x/bridge/keeper/msg_server_push_new_actions.go index c68ba4d9..8540239a 100644 --- a/x/bridge/keeper/msg_server_push_new_actions.go +++ b/x/bridge/keeper/msg_server_push_new_actions.go @@ -4,6 +4,7 @@ import ( "context" errorsmod "cosmossdk.io/errors" + merkle "github.com/node101-io/mina-signer-go/merklelist" "github.com/node101-io/pulsar-chain/x/bridge/types" ) @@ -30,6 +31,12 @@ func (k msgServer) PushNewActions(ctx context.Context, msg *types.MsgPushNewActi if err != nil { return nil, err } + + list, err := merkle.NewMerkleListFromRoot(types.MerkleListPrefix, bridgeState.ActionsReducedRoot) + if err != nil { + return nil, err + } + for _, act := range actions { valid, err := k.isValid(ctx, &act) @@ -43,11 +50,20 @@ func (k msgServer) PushNewActions(ctx context.Context, msg *types.MsgPushNewActi return nil, err } + bz, err := act.Marshal() + if err != nil { + return nil, err + } + + if err := list.Append(bz); err != nil { + return nil, err + } + } if err := k.Keeper.setBridgeState(ctx, types.BridgeState{ LatestFetchedMinaHeight: msg.MinaBlockHeight, - ActionsReducedRoot: []byte(""), + ActionsReducedRoot: list.Root(), }); err != nil { return nil, err } From 7a1e1e5ba4111d525714fbd80b7bd4f2435b90a4 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Mon, 1 Jun 2026 21:39:35 +0300 Subject: [PATCH 63/63] fix: wire bridge module into the app --- app/app_config.go | 11 +++++++++++ docs/static/openapi.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/app_config.go b/app/app_config.go index dc747fa5..fd2e8f2b 100644 --- a/app/app_config.go +++ b/app/app_config.go @@ -3,6 +3,8 @@ package app import ( "time" + _ "github.com/node101-io/pulsar-chain/x/bridge/module" + bridgemoduletypes "github.com/node101-io/pulsar-chain/x/bridge/types" _ "github.com/node101-io/pulsar-chain/x/keyregistry/module" keyregistrymoduletypes "github.com/node101-io/pulsar-chain/x/keyregistry/types" _ "github.com/node101-io/pulsar-chain/x/pulsar/module" @@ -88,6 +90,7 @@ var ( {Account: nft.ModuleName}, {Account: ibctransfertypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner}}, {Account: icatypes.ModuleName}, + {Account: bridgemoduletypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner}}, } // blocked account addresses @@ -98,6 +101,7 @@ var ( stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, nft.ModuleName, + bridgemoduletypes.ModuleName, // We allow the following module accounts to receive funds: // govtypes.ModuleName } @@ -133,6 +137,7 @@ var ( pulsarmoduletypes.ModuleName, keyregistrymoduletypes.ModuleName, votepersistencemoduletypes.ModuleName, + bridgemoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/beginBlockers }, EndBlockers: []string{ @@ -144,6 +149,7 @@ var ( pulsarmoduletypes.ModuleName, keyregistrymoduletypes.ModuleName, votepersistencemoduletypes.ModuleName, + bridgemoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/endBlockers }, // The following is mostly only needed when ModuleName != StoreKey name. @@ -183,6 +189,7 @@ var ( pulsarmoduletypes.ModuleName, keyregistrymoduletypes.ModuleName, votepersistencemoduletypes.ModuleName, + bridgemoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/initGenesis }, }), @@ -279,6 +286,10 @@ var ( Name: epochstypes.ModuleName, Config: appconfig.WrapAny(&epochsmodulev1.Module{}), }, + { + Name: bridgemoduletypes.ModuleName, + Config: appconfig.WrapAny(&bridgemoduletypes.Module{}), + }, { Name: pulsarmoduletypes.ModuleName, Config: appconfig.WrapAny(&pulsarmoduletypes.Module{}), diff --git a/docs/static/openapi.json b/docs/static/openapi.json index b3232407..ad0dae3b 100644 --- a/docs/static/openapi.json +++ b/docs/static/openapi.json @@ -1 +1 @@ -{"id":"github.com/node101-io/pulsar-chain","consumes":["application/json"],"produces":["application/json"],"swagger":"2.0","info":{"description":"Chain github.com/node101-io/pulsar-chain REST API","title":"HTTP API Console","contact":{"name":"github.com/node101-io/pulsar-chain"},"version":"version not set"},"paths":{"/node101-io/pulsar-chain/keyregistry/v1/get_user_cosmos_public_key/{user_mina_public_key}":{"get":{"tags":["Query"],"summary":"GetUserCosmosPublicKey Queries a list of GetUserCosmosPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserCosmosPublicKey","parameters":[{"type":"string","format":"byte","name":"user_mina_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_user_mina_public_key/{user_cosmos_public_key}":{"get":{"tags":["Query"],"summary":"GetUserMinaPublicKey Queries a list of GetUserMinaPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserMinaPublicKey","parameters":[{"type":"string","format":"byte","name":"user_cosmos_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_cosmos_pub_key/{validator_mina_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorCosmosPubKey Queries a list of GetValidatorCosmosPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorCosmosPubKey","parameters":[{"type":"string","format":"byte","name":"validator_mina_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_mina_pub_key/{validator_cosmos_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorMinaPubKey Queries a list of GetValidatorMinaPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorMinaPubKey","parameters":[{"type":"string","format":"byte","name":"validator_cosmos_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin9","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin13","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/vote_ext_body_by_height/{block_height}":{"get":{"tags":["Query"],"summary":"VoteExtBodyByHeight queries the vote extension body for a block height.","operationId":"GithubComnode101IopulsarChainQuery_VoteExtBodyByHeight","parameters":[{"type":"string","format":"int64","name":"block_height","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.QueryVoteExtBodyByHeightResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/vote_extensions":{"get":{"tags":["Query"],"summary":"VoteExtensions queries the currently persisted vote extensions.","operationId":"GithubComnode101IopulsarChainQuery_VoteExtensions","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.QueryVoteExtensionsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/pulsar/pulsar/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_Params","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsar.pulsar.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}}},"definitions":{"google.protobuf.Any":{"type":"object","properties":{"@type":{"type":"string"}},"additionalProperties":{}},"google.rpc.Status":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"details":{"type":"array","items":{"type":"object","$ref":"#/definitions/google.protobuf.Any"}},"message":{"type":"string"}}},"pulsar.pulsar.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsar.pulsar.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsar.pulsar.v1.Params"}}},"pulsarchain.keyregistry.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse":{"description":"QueryGetUserCosmosPublicKeyResponse defines the QueryGetUserCosmosPublicKeyResponse message.","type":"object","properties":{"user_cosmos_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse":{"description":"QueryGetUserMinaPublicKeyResponse defines the QueryGetUserMinaPublicKeyResponse message.","type":"object","properties":{"user_mina_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse":{"description":"QueryGetValidatorCosmosPubKeyResponse defines the QueryGetValidatorCosmosPubKeyResponse message.","type":"object","properties":{"validator_cosmos_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse":{"description":"QueryGetValidatorMinaPubKeyResponse defines the QueryGetValidatorMinaPubKeyResponse message.","type":"object","properties":{"validator_mina_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.keyregistry.v1.Params"}}},"pulsarchain.votepersistence.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.votepersistence.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.votepersistence.v1.Params"}}},"pulsarchain.votepersistence.v1.QueryVoteExtBodyByHeightResponse":{"description":"QueryVoteExtBodyByHeightResponse defines the QueryVoteExtBodyByHeightResponse message.","type":"object","properties":{"vote_ext_body":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.VoteExtBody"}}},"pulsarchain.votepersistence.v1.QueryVoteExtensionsResponse":{"description":"QueryVoteExtensionsResponse defines the QueryVoteExtensionsResponse message.","type":"object","properties":{"persisted_vote_extensions_block_height":{"type":"string","format":"int64"},"query_block_height":{"type":"string","format":"int64"},"vote_extensions":{"type":"array","items":{"type":"object","$ref":"#/definitions/pulsarchain.votepersistence.v1.StoredVoteExtension"}}}},"pulsarchain.votepersistence.v1.StoredVoteExtension":{"description":"StoredVoteExtension defines a persisted Mina validator vote extension.","type":"object","properties":{"mina_public_key":{"type":"string","format":"byte"},"vote_extension":{"type":"string","format":"byte"}}},"pulsarchain.votepersistence.v1.VoteExtBody":{"description":"VoteExtBody defines the VoteExtBody message.","type":"object","properties":{"actions_reduced_root":{"type":"string"},"current_block_height":{"type":"string","format":"int64"},"current_state_root":{"type":"string","format":"byte"},"next_validator_set_hash":{"type":"string","format":"byte"}}}},"tags":[{"name":"Query"},{"name":"Msg"}]} \ No newline at end of file +{"id":"github.com/node101-io/pulsar-chain","consumes":["application/json"],"produces":["application/json"],"swagger":"2.0","info":{"description":"Chain github.com/node101-io/pulsar-chain REST API","title":"HTTP API Console","contact":{"name":"github.com/node101-io/pulsar-chain"},"version":"version not set"},"paths":{"/node101-io/pulsar-chain/abci/v1/vote_ext_body_by_height/{vote_extension_height}":{"get":{"tags":["Query"],"summary":"VoteExtBodyByHeight queries the vote extension body for a vote-extension\nconsensus height.","operationId":"GithubComnode101IopulsarChainQuery_VoteExtBodyByHeight","parameters":[{"type":"string","format":"int64","description":"vote_extension_height is the consensus height N where the vote extension is\nproduced. The returned body signs the transition from state N-2 to state N-1.","name":"vote_extension_height","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.abci.QueryVoteExtBodyByHeightResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/bridge/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin10","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.bridge.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_user_cosmos_public_key/{user_mina_public_key}":{"get":{"tags":["Query"],"summary":"GetUserCosmosPublicKey Queries a list of GetUserCosmosPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserCosmosPublicKey","parameters":[{"type":"string","format":"byte","name":"user_mina_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_user_mina_public_key/{user_cosmos_public_key}":{"get":{"tags":["Query"],"summary":"GetUserMinaPublicKey Queries a list of GetUserMinaPublicKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetUserMinaPublicKey","parameters":[{"type":"string","format":"byte","name":"user_cosmos_public_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_cosmos_pub_key/{validator_mina_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorCosmosPubKey Queries a list of GetValidatorCosmosPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorCosmosPubKey","parameters":[{"type":"string","format":"byte","name":"validator_mina_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/get_validator_mina_pub_key/{validator_cosmos_pub_key}":{"get":{"tags":["Query"],"summary":"GetValidatorMinaPubKey Queries a list of GetValidatorMinaPubKey items.","operationId":"GithubComnode101IopulsarChainQuery_GetValidatorMinaPubKey","parameters":[{"type":"string","format":"byte","name":"validator_cosmos_pub_key","in":"path","required":true}],"responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/keyregistry/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin16","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.keyregistry.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_ParamsMixin20","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/node101-io/pulsar-chain/votepersistence/v1/vote_extensions":{"get":{"tags":["Query"],"summary":"VoteExtensions queries the currently persisted vote extensions.","operationId":"GithubComnode101IopulsarChainQuery_VoteExtensions","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.QueryVoteExtensionsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}},"/pulsar/pulsar/v1/params":{"get":{"tags":["Query"],"summary":"Parameters queries the parameters of the module.","operationId":"GithubComnode101IopulsarChainQuery_Params","responses":{"200":{"description":"A successful response.","schema":{"$ref":"#/definitions/pulsar.pulsar.v1.QueryParamsResponse"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/google.rpc.Status"}}}}}},"definitions":{"google.protobuf.Any":{"type":"object","properties":{"@type":{"type":"string"}},"additionalProperties":{}},"google.rpc.Status":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"details":{"type":"array","items":{"type":"object","$ref":"#/definitions/google.protobuf.Any"}},"message":{"type":"string"}}},"pulsar.pulsar.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsar.pulsar.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsar.pulsar.v1.Params"}}},"pulsarchain.abci.QueryVoteExtBodyByHeightResponse":{"description":"QueryVoteExtBodyByHeightResponse defines the response for VoteExtBodyByHeight.","type":"object","properties":{"vote_ext_body":{"$ref":"#/definitions/pulsarchain.votepersistence.v1.VoteExtBody"}}},"pulsarchain.bridge.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.bridge.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.bridge.v1.Params"}}},"pulsarchain.keyregistry.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.keyregistry.v1.QueryGetUserCosmosPublicKeyResponse":{"description":"QueryGetUserCosmosPublicKeyResponse defines the QueryGetUserCosmosPublicKeyResponse message.","type":"object","properties":{"user_cosmos_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetUserMinaPublicKeyResponse":{"description":"QueryGetUserMinaPublicKeyResponse defines the QueryGetUserMinaPublicKeyResponse message.","type":"object","properties":{"user_mina_public_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorCosmosPubKeyResponse":{"description":"QueryGetValidatorCosmosPubKeyResponse defines the QueryGetValidatorCosmosPubKeyResponse message.","type":"object","properties":{"validator_cosmos_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryGetValidatorMinaPubKeyResponse":{"description":"QueryGetValidatorMinaPubKeyResponse defines the QueryGetValidatorMinaPubKeyResponse message.","type":"object","properties":{"validator_mina_pub_key":{"type":"string","format":"byte"}}},"pulsarchain.keyregistry.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.keyregistry.v1.Params"}}},"pulsarchain.votepersistence.v1.Params":{"description":"Params defines the parameters for the module.","type":"object"},"pulsarchain.votepersistence.v1.QueryParamsResponse":{"description":"QueryParamsResponse is response type for the Query/Params RPC method.","type":"object","properties":{"params":{"description":"params holds all the parameters of this module.","$ref":"#/definitions/pulsarchain.votepersistence.v1.Params"}}},"pulsarchain.votepersistence.v1.QueryVoteExtensionsResponse":{"description":"QueryVoteExtensionsResponse defines the QueryVoteExtensionsResponse message.","type":"object","properties":{"persisted_vote_extensions_block_height":{"description":"persisted_vote_extensions_block_height is the signed source/current state\nheight. For vote extensions produced at height N, this value is N-2.","type":"string","format":"int64"},"query_block_height":{"type":"string","format":"int64"},"vote_extensions":{"type":"array","items":{"type":"object","$ref":"#/definitions/pulsarchain.votepersistence.v1.StoredVoteExtension"}}}},"pulsarchain.votepersistence.v1.StoredVoteExtension":{"description":"StoredVoteExtension defines a persisted Mina validator vote extension.","type":"object","properties":{"mina_public_key":{"type":"string","format":"byte"},"vote_extension":{"type":"string","format":"byte"}}},"pulsarchain.votepersistence.v1.VoteExtBody":{"description":"VoteExtBody defines the VoteExtBody message.","type":"object","properties":{"actions_reduced_root":{"type":"string"},"current_block_height":{"type":"string","format":"int64"},"current_state_root":{"type":"string","format":"byte"},"next_validator_set_hash":{"type":"string","format":"byte"}}}},"tags":[{"name":"Query"},{"name":"Msg"}]} \ No newline at end of file