diff --git a/.gitignore b/.gitignore index f8070ec071..d6961a9b17 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ frontend/.cache secret.yml build coverage.txt +.idea +.vscode tools-stamp .vscode profile.out diff --git a/Makefile b/Makefile index cd13721341..bb7eb9bf9f 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ test: .PHONY: test proto-gen: - $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace tendermintdev/sdk-proto-gen:latest sh ./scripts/protocgen.sh + $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace tendermintdev/sdk-proto-gen:v0.7 sh ./scripts/protocgen.sh proto-lint: @$(DOCKER_BUF) lint --error-format=json diff --git a/app/app.go b/app/app.go index 9fdc3ba198..14097d876a 100644 --- a/app/app.go +++ b/app/app.go @@ -310,10 +310,21 @@ func New( app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper) app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String()) + app.QgbKeeper = *qgbmodulekeeper.NewKeeper( + appCodec, + keys[qgbmoduletypes.StoreKey], + app.GetSubspace(qgbmoduletypes.ModuleName), + &stakingKeeper, + ) + qgbmod := qgbmodule.NewAppModule(appCodec, app.QgbKeeper) + // register the staking hooks // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks app.StakingKeeper = *stakingKeeper.SetHooks( - stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()), + stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), + app.SlashingKeeper.Hooks(), + app.QgbKeeper.Hooks(), + ), ) // ... other modules keepers @@ -329,7 +340,7 @@ func New( AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)) - // AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) + // AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) // Create Transfer Keepers // app.TransferKeeper = ibctransferkeeper.NewKeeper( @@ -357,14 +368,7 @@ func New( app.PaymentKeeper = *paymentmodulekeeper.NewKeeper( appCodec, ) - paymentmodule := paymentmodule.NewAppModule(appCodec, app.PaymentKeeper) - - app.QgbKeeper = *qgbmodulekeeper.NewKeeper( - appCodec, - keys[qgbmoduletypes.StoreKey], - keys[qgbmoduletypes.MemStoreKey], - ) - qgbmodule := qgbmodule.NewAppModule(appCodec, app.QgbKeeper) + paymentmod := paymentmodule.NewAppModule(appCodec, app.PaymentKeeper) // // Create static IBC router, add transfer route, then set and seal it // ibcRouter := ibcporttypes.NewRouter() @@ -401,8 +405,8 @@ func New( // ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), // transferModule, - paymentmodule, - qgbmodule, + paymentmod, + qgbmod, ) // During begin block slashing happens after distr.BeginBlocker so that diff --git a/docs/architecture/ADR-002-QGB-ValSet.md b/docs/architecture/ADR-002-QGB-ValSet.md new file mode 100644 index 0000000000..b7a7b9f29a --- /dev/null +++ b/docs/architecture/ADR-002-QGB-ValSet.md @@ -0,0 +1,338 @@ +# ADR 002: QGB ValSet + +## Context + +To accommodate the requirements of the [Quantum Gravity Bridge](https://github.com/celestiaorg/quantum-gravity-bridge/blob/master/ethereum/solidity/src/QuantumGravityBridge.sol), We will need to add support for `ValSet`s, i.e. Validator Sets, which reflect the current state of the bridge validators. + +## Decision + +Add the `ValSet` and `ValSetConfirm` type of messages in order to track the state of the validator set. + +PS: The `ValsetConfirm` have been updated in `ADR-005-QGB_reduce_state_usage`. Please take a look on it to know how we will be handling the confirms. + +## Detailed Design + +Since the QGB is only a one way bridge and is not transferring assets, it doesn't require the portions of the gravity module that recreate state from the bridged chain. We only need to keep things relating to signing over the validator set (such as`MsgSetOrchestratorAddress` and `MsgValsetConfirm`) and relayer queries (such as `ValsetConfirm` and `GetDelegateKeyByOrchestrator`). + +It works by relying on a set of signers to attest to some event on Celestia: the Celestia validator set. + +The QGB contract keeps track of the Celestia validator set by updating its view of the validator set with `updateValidatorSet()`. More than 2/3 of the voting power of the current view of the validator set must sign off on new relayed events, submitted with +[`submitDataRootTupleRoot()`](https://github.com/celestiaorg/quantum-gravity-bridge/blob/980b9c68abc34b8d2e4d20ca644b8aa3025a239e/ethereum/solidity/src/QuantumGravityBridge.sol#L328). +Each event is a batch of `DataRootTuples`, with each tuple representing a single data root (i.e. block header). Relayed tuples are in the same order as Celestia block headers. +For more details, check the data commitment ADR. + +Finally, if there are no validator set updates for the unbonding window, the bridge must halt. + +### When are validator sets created + +1. If there are no valSet requests, create a new one +2. If there is at least one validator who started unbonding in current block. (we persist last unbonded block height in `hooks.go`) + This will make sure the unbonding validator has to provide an attestation to a new ValSet + that excludes him before he completely unbonds. Otherwise, he will be slashed. +3. If power change between validators of CurrentValSet and latest valSet request is > 5% + +### Message types + +We added the following messages types: + +#### Bridge Validator + +The `BridgeValidator` represents a validator's ETH address and its power. + +```protobuf +message BridgeValidator { + // Voting power of the validator. + uint64 power = 1; + // Ethereum address that will be used by the validator to sign messages. + string ethereum_address = 2; +} +``` + +#### ValSet + +`Valset` is the Ethereum Bridge Multsig Set, each qgb validator also maintains an ETH key to sign messages, these are used to check signatures on ETH because of the significant gas savings. + +```protobuf +message Valset { + // Unique number referencing the `ValSet`. + uint64 nonce = 1; + // List of BridgeValidator containing the current validator set. + repeated BridgeValidator members = 2 [ (gogoproto.nullable) = false ]; + // Current chain height + uint64 height = 3; +} +``` + +#### MsgSetOrchestratorAddress + +`MsgSetOrchestratorAddress` allows validators to delegate their voting responsibilities to a given key. This key is then used as an optional authentication method for signing oracle claims. + +```protobuf +message MsgSetOrchestratorAddress { + // The validator field is a celesvaloper1... string (i.e. sdk.ValAddress) + // that references a validator in the active set + string validator = 1; + // The orchestrator field is a celes1... string (i.e. sdk.AccAddress) that + // references the key that is being delegated to + string orchestrator = 2; + // This is a hex encoded 0x Ethereum public key that will be used by this + // validator on Ethereum + string eth_address = 3; +} +``` + +#### ValSetConfirmfix last e2e tests + +`MsgValsetConfirm` is the message sent by the validators when they wish to submit their signatures over the validator set at a given block height. A validator must first call `SetOrchestratorAddress` to set their Ethereum's address to be used for signing. Then, using `EndBlocker()`, the protocol makes a `ValsetRequest`, the request is essentially a messaging mechanism to determine which block all validators should submit signatures over. Finally, validators sign the `validator set`, `powers`, and `Ethereum addresses` of the entire validator set at the height of a `Valset` and submit that signature with this message. + +If a sufficient number of validators (66% of voting power): + +- have set Ethereum addresses and, +- submit `ValsetConfirm` messages with their signatures, + +it is then possible for anyone to view these signatures in the chain store and submit them to Ethereum to update the validator set. + +```protobuf +message MsgValsetConfirm { + // Unique number referencing the `ValSet`. + uint64 nonce = 1; + // Orchestrator `celes1` account address. + string orchestrator = 2; + // Ethereum address, associated to the orchestrator, used to sign the `ValSet` + // message. + string eth_address = 3; + // The `ValSet` message signature. + string signature = 4; +} + +``` + +### ValSetRequest Handling + +`ValSetRequest`s are created at the `EndBlocker` function: + +```go +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + ... +} +``` + +#### Get latest valset and unbonding height + +We start by getting the latest valset, unbonding height and also initializing the power difference between valsets. + +```go +latestValset := k.GetLatestValset(ctx) +lastUnbondingHeight := k.GetLastUnBondingBlockHeight(ctx) +significantPowerDiff := false +``` + +#### Check if there was a signification power difference between valsets + +If the previous valset is not null, then we had a previous set of validators defining a certain power. +We check if the current valset power is significantly different from the previous one. If so, we set the `significantPowerDiff` to true. + +The significance of power difference is calculated using a pre-defined constant. Currently, it is defined as: + +```go +// SignificantPowerDifferenceThreshold the threshold of change in the validator set power +// that would need the creation of a new valset request. +const SignificantPowerDifferenceThreshold = 0.05 +``` + +For more information on the normalization of power, check [here](https://github.com/celestiaorg/celestia-app/blob/df46d122da5f1fab1bd99bfb2bfcf9002f5bc154/x/qgb/types/validator.go#L101 +). + +#### Create a ValSet + +Finally, if one of the following conditions hold: + +- There was no valsets already committed to. +- The power difference between the previous valsets and the current one is significant. +- A validator started unbonding in the current block height. + +We set a new valset request to be signed by the network and ultimately submitted to the QGB contracts. + +```go +if (latestValset == nil) || (lastUnbondingHeight == uint64(ctx.BlockHeight())) || significantPowerDiff { + // if the conditions are true, put in a new validator set request to be signed and submitted to Ethereum + k.SetValsetRequest(ctx) +} +``` + +### ValSetConfirm Processing + +Upon receiving a `MsgValSetConfirm`, we go for the following: + +#### ValSet check + +We start off by checking if the `ValSet` referenced by the provided `nonce` exists. If so, we get it. If not, we return an error: + +```go +valset := k.GetValset(ctx, msg.Nonce) +if valset == nil { + return nil, sdkerrors.Wrap(types.ErrInvalid, "couldn't find valset") +} +``` + +#### Check the address and signature + +Next, we check the orchestrator address: + +```go +orchaddr, err := sdk.AccAddressFromBech32(msg.Orchestrator) +if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalid, "acc address invalid") +} +``` + +Then, we verify if the signature is well-formed, and it is signed using a private key whose address is the one sent in the request: + +```go +err = k.confirmHandlerCommon(ctx, msg.EthAddress, msg.Orchestrator, msg.Signature) +if err != nil { + return nil, err +} +// persist signature +if k.GetValsetConfirm(ctx, msg.Nonce, orchaddr) != nil { + return nil, sdkerrors.Wrap(types.ErrDuplicate, "signature duplicate") +} +``` + +The `confirmHandlerCommon` is an internal function that provides common code for processing signatures: + +```go +func (k msgServer) confirmHandlerCommon(ctx sdk.Context, ethAddress string, orchestrator string, signature string) error { + _, err := hex.DecodeString(signature) + if err != nil { + return sdkerrors.Wrap(types.ErrInvalid, "signature decoding") + } + + submittedEthAddress, err := types.NewEthAddress(ethAddress) + if err != nil { + return sdkerrors.Wrap(types.ErrInvalid, "invalid eth address") + } + + orchaddr, err := sdk.AccAddressFromBech32(orchestrator) + if err != nil { + return sdkerrors.Wrap(types.ErrInvalid, "acc address invalid") + } + validator, found := k.GetOrchestratorValidator(ctx, orchaddr) + if !found { + return sdkerrors.Wrap(types.ErrUnknown, "validator") + } + if err := sdk.VerifyAddressFormat(validator.GetOperator()); err != nil { + return sdkerrors.Wrapf(err, "discovered invalid validator address for orchestrator %v", orchaddr) + } + + ethAddressFromStore, found := k.GetEthAddressByValidator(ctx, validator.GetOperator()) + if !found { + return sdkerrors.Wrap(types.ErrEmpty, "no eth address set for validator") + } + + if *ethAddressFromStore != *submittedEthAddress { + return sdkerrors.Wrap(types.ErrInvalid, "submitted eth address does not match delegate eth address") + } + return nil +} +``` + +And, then check if the signature is a duplicate, i.e. whether another `ValSetConfirm` reflecting the same truth has already been committed to. + +#### Persist the ValSet confirm and emit an event + +Lastly, we persist the `ValSetConfirm` message and broadcast an event: + +```go +key := k.SetValsetConfirm(ctx, *msg) +ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, msg.Type()), + sdk.NewAttribute(types.AttributeKeyValsetConfirmKey, string(key)), + ), +) +``` + +### SetOrchestratorAddress Processing + +Upon receiving a `MsgSetOrchestratorAddress`, we go for the following: + +#### Basic validation + +We start off by validating the parameters: + +```go +// ensure that this passes validation, checks the key validity +err := msg.ValidateBasic() +if err != nil { + return nil, sdkerrors.Wrap(err, "Key not valid") +} +ctx := sdk.UnwrapSDKContext(c) + +// check the following, all should be validated in validate basic +val, e1 := sdk.ValAddressFromBech32(msg.Validator) +orch, e2 := sdk.AccAddressFromBech32(msg.Orchestrator) +addr, e3 := types.NewEthAddress(msg.EthAddress) +if e1 != nil || e2 != nil || e3 != nil { + return nil, sdkerrors.Wrap(err, "Key not valid") +} + +// check that the validator does not have an existing key +_, foundExistingOrchestratorKey := k.GetOrchestratorValidator(ctx, orch) +_, foundExistingEthAddress := k.GetEthAddressByValidator(ctx, val) + +// ensure that the validator exists +if foundExistingOrchestratorKey || foundExistingEthAddress { + return nil, sdkerrors.Wrap(types.ErrResetDelegateKeys, val.String()) +} +``` + +Then, verify that neither keys is a duplicate: + +```go +// check that neither key is a duplicate +delegateKeys := k.GetDelegateKeys(ctx) +for i := range delegateKeys { + if delegateKeys[i].EthAddress == addr.GetAddress() { + return nil, sdkerrors.Wrap(err, "Duplicate Ethereum Key") + } + if delegateKeys[i].Orchestrator == orch.String() { + return nil, sdkerrors.Wrap(err, "Duplicate Orchestrator Key") + } +} +``` + +#### Persist the Orchestrator and Ethereum address and emit an event + +Lastly, we persist the orchestrator validator address: + +```go +k.SetOrchestratorValidator(ctx, val, orch) +``` + +Then, we set the corresponding Ethereum address: + +```go +k.SetEthAddressForValidator(ctx, val, *addr) +``` + +And finally, emit an event: + +```go +ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, msg.Type()), + sdk.NewAttribute(types.AttributeKeySetOperatorAddr, orch.String()), + ), +) +``` + +## Status + +Accepted + +## References + +- {reference link} diff --git a/docs/architecture/ADR-003-QGB-DataCommitment.md b/docs/architecture/ADR-003-QGB-DataCommitment.md new file mode 100644 index 0000000000..d9e2714b6f --- /dev/null +++ b/docs/architecture/ADR-003-QGB-DataCommitment.md @@ -0,0 +1,139 @@ +# ADR 003: QGB Data Commitments + +## Context + +To accommodate the requirements of the [Quantum Gravity Bridge](https://github.com/celestiaorg/quantum-gravity-bridge/blob/master/ethereum/solidity/src/QuantumGravityBridge.sol), We will need to add support for `DataCommitment`s messages, i.e. commitments generated over a set of blocks to attest their existence. + +## Decision + +Add the `DataCommitmentConfirm` type of messages in order to attest that a set of blocks has been finalized. + +PS: The `ValsetConfirm` have been updated in `ADR-005-QGB_reduce_state_usage`. Please take a look on it to know how we will be handling the confirms. + +## Detailed Design + +To accommodate the QGB, validators need a way to submit signatures for a data commitments so that relayers can easily find them and submit them to the bridged chain. To do this, we will introduce `MsgDataCommitmentConfirm` messages. This latter will be persisted for the sole reason of slashing. If not for that, a P2P network would do the job. + +Data commitment messages attest that a certain set of blocks have been committed to in the Celestia chain. These commitments are used to update the data commitment checkpoint defined in the Ethereum smart contract of the QGB. + +Thus, they will contain the commitments along the signatures and will be used to check if an attestation has been signed by 2/3+ of the network validators and can be committed to the bridge contract. + +### MsgDataCommitmentConfirm + +`MsgDataCommitmentConfirm` describe a data commitment for a set of blocks signed by an orchestrator. + +```protobuf +message MsgDataCommitmentConfirm { + // Signature over the commitment, the range of blocks, the validator address + // and the Ethereum address. + string signature = 1; + // Orchestrator account address who will be signing the message. + string validator_address = 2; + // Hex `0x` encoded Ethereum public key that will be used by this validator on + // Ethereum. + string eth_address = 3; + // Merkle root over a merkle tree containing the data roots of a set of + // blocks. + string commitment = 4; + // First block defining the ordered set of blocks used to create the + // commitment. + int64 begin_block = 5; + // Last block defining the ordered set of blocks used to create the + // commitment. + int64 end_block = 6; +} +``` + +#### Data commitment message processing + +When handling a `MsgDataCommitmentConfirm`, we go for the following: + +#### Verify the signature + +We start off by verifying if the signature is well-formed, and return an error if not: + +```go +sigBytes, err := hex.DecodeString(msg.Signature) +if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalid, "signature decoding") +} +``` + +This is done first as the whole concept revolves around signing commitments. Thus, if a signature is mal-formed, there is no need to continue. + +#### Verify addresses + +Then, we verify the provided address and check if an orchestrator exists for the provided address: + +```go +validatorAddress, err := sdk.AccAddressFromBech32(msg.ValidatorAddress) +if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalid, "validator address invalid") +} +validator, found := k.GetOrchestratorValidator(ctx, validatorAddress) +if !found { + return nil, sdkerrors.Wrap(types.ErrUnknown, "validator") +} +if err := sdk.VerifyAddressFormat(validator.GetOperator()); err != nil { + return nil, sdkerrors.Wrapf(err, "discovered invalid validator address for validator %v", validatorAddress) +} +``` + +#### Verify Ethereum address and check signature + +Next, we verify the Ethereum address and check if it was used to create the signature: + +```go +ethAddress, err := types.NewEthAddress(msg.EthAddress) +if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalid, "invalid eth address") +} +err = types.ValidateEthereumSignature([]byte(msg.Commitment), sigBytes, *ethAddress) +if err != nil { + return nil, + sdkerrors.Wrap( + types.ErrInvalid, + fmt.Sprintf( + "signature verification failed expected sig by %s with checkpoint %s found %s", + ethAddress, + msg.Commitment, + msg.Signature, + ), + ) +} +ethAddressFromStore, found := k.GetEthAddressByValidator(ctx, validator.GetOperator()) +if !found { + return nil, sdkerrors.Wrap(types.ErrEmpty, "no eth address set for validator") +} +if *ethAddressFromStore != *ethAddress { + return nil, sdkerrors.Wrap(types.ErrInvalid, "submitted eth address does not match delegate eth address") +} +``` + +#### Set the data commitment confirm and send event + +After checking that the message is valid, the addresses are correct and the signature is legit, we proceed to persist this data commitment confirm message: + +```go +k.SetDataCommitmentConfirm(ctx, *msg) +``` + +Then, we continue to broadcast an event containing the message: + +```go +ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, msg.Type()), + sdk.NewAttribute(types.AttributeKeyDataCommitmentConfirmKey, msg.String()), + ), +) +``` + +## Status + +Accepted + +## References + +- {reference link} diff --git a/docs/architecture/ADR-004-QGB_relayer_security.md b/docs/architecture/ADR-004-QGB_relayer_security.md new file mode 100644 index 0000000000..6ebaefc238 --- /dev/null +++ b/docs/architecture/ADR-004-QGB_relayer_security.md @@ -0,0 +1,406 @@ +# ADR 4: QGB Relayer security design + +## Changelog + +- 2022-06-05: Synchronous QGB implementation + +## Context + +The current QGB design requires relayers to relay everything in a perfect synchronous order, but the contracts do not. +In fact, the QGB smart contract is designed to update the data commitments as follows: + +- Receive a data commitment +- Check that the block height (nonce) is higher than the previously committed root +- Check if the data commitment is signed using the current valset _(this is the problematic check)_ +- Then, other checks + commit + +So, if a relayer is up to date, it will submit data commitment and will pass the above checks. + +Now, if the relayer is missing some data commitments or valset updates, then it will start catching up the following way: + +- Relay valset +- Keep relaying all data commitments that were signed using that valset +- If a new valset is found, check that: up to the block where the valset was changed, all the data commitments that happened during that period are relayed +- Relay the next valset +- And, so on. + +The problem with this approach is that there is constant risk for any relayer to mess the ordering of the attestations submission, ie relaying the next valset before relaying all the data commitments that were signed using the previous valset, and end up with signatures holes. + +Also, a malicious relayer, can target any honest QGB relayer in normal mode, or while catching up, and mess its attestations submission order, as follows: + +- Get the latest relayed valset +- Listen for new signed valsets +- Once a new valset is signed by 2/3 of the network, submit it immediately to be included in next block without waiting for the data commitments to be relayed also + +Then, this would create holes in the signatures as the honest relayer will no longer be able to submit the previous data commitments as they're not, in general, signed by the valset relayed by the malicious relayer. And the only solution is to jump to the ones that were signed with the current valset. + +## Alternative Approaches + +### More synchrony : Deploy the QGB contract with a data commitment window + +When deploying the QGB contract, also set the data commitment window, ie, the number of blocks between the `beginBlock` and `endBlock` of each data commitment confirm. + +Then, update the QGB contract to check when receiving a new valset if the latest relayed data commitment height is >= new valset height - data commitment window. + +This also would mean adding, for example, a `DataCommitmentWindowConfirm` representing signatures of the validator set for a certain `DataCommitmentWindow`, since this latter can be updated using gov proposals. + +- Cons: + - More complexity and state in the contract +- Pros: + - Fix the race condition issue + +### Synchronous QGB : Universal nonce approach + +This approach consists of switching to a synchronous QGB design utilizing universal nonces. This means, the `ValsetConfirm`s and `DataCommitmentConfirm`s will have the same nonce being incremented on each attestations. Then, the QGB contract will check against this universal nonce and only accept an attestations if its nonce is incremented by 1. + +- Cons: + - Unifiying the `ValsetConfirm`s and `DataCommitmentConfirm`s under the same nonce even if they represent separate concepts. +- Pros: + - Simpler QGB smart contract + +### Add more state to the contract : Store valsets and their nonce + +Update the QGB contract to store the valset hashes + their nonces: + +- Cons: + - Would make the contract more complex +- Pros: + - Would make the relayer parallelizable (can submit data commitments and valsets in any order as long as the valset is committed) + - would allow the QGB to catchup correctly even in the existence of a malicious relayer + +### A request oriented design + +Currently, the attestations that need to be signed are defined by the state machine based on `abci.endBlock()` and a `DataCommitmentWindow`. This simplifies the state machine and doesn't require implementing new transaction types to ask for orchestrators signatures. + +The request oriented design means providing users (relayers mainly) with the ability to post data commitment requests and ask orchestrators to sign them. + +The main issue with this approach is spamming and state bloat. In fact, allowing attestations signatures' requests would allow anyone to spam the network with unnecessary signatures and make orchestrators do unnecessary work. This gets worse if signatures are part of the state, since this latter is costly. + +A proposition to remediate the issues described above is to make the signatures part of the block data in specific namespaces. Then, we can charge per request and even make asking for attestations signatures a bit costly. + +- Pros + - Would allow anyone to ask for signatures over commitments, ie, the QGB can then be used by any team without changing anything. +- Cons + - Makes slashing more complicated. In fact, to slash for liveness, providing the whole history of blocks, proving that a certain orchestrator didn't sign an attestation in the given period, will be hard to implement and the proofs will be big. Compared to the attestations being part of the state, which can be queried easilly. + +## Decision + +The **Synchronous QGB : Universal nonce approach** will be implemented as it will allow us to ship a working QGB 1.0 version faster while preserving the same security assumptions at the expense of parallelization, and custumization, as discussed under the _request oriented design_ above. + +## Detailed Design + +### AttestationRequestI + +The **Synchronous QGB : Universal nonce approach** means that the data commitment requests and valset requests will be ordered following the same nonce. + +In order to achieve this, we will need to either: + +- Have a separate nonce for each and define ordering conditions when updating them to guarantee the universal order. +- Define an abstraction of the data commitment requests and valsets that guarantees the order. Then, link it to the concrete types. + +In our implementation, we will go for the second approach. + +#### Interface implementation + +To do so, we will first need to define the interface `AttestationRequestI`: + +```go +type AttestationRequestI interface { + proto.Message + codec.ProtoMarshaler + Type() AttestationType + GetNonce() uint64 +} +``` + +This interface implements the `proto.Message` so that it can be handled by protobuf messages. Also, it implements the `codec.ProtoMarshaler` to be marshalled/unmarshaled by protobuf. + +Then, it contains a method `Type() AttestationType` which returns the attestation type which can be one of the following: + +- `DataCommitmentRequestType`: for data commitment requests +- `ValsetRequestType`: for valset requests + +```go +type AttestationType int64 + +const ( + DataCommitmentRequestType AttestationType = iota + ValsetRequestType +) +``` + +Finally, a method `GetNonce() uint64` which keeps track of the nonce and returns it. + +#### Protobuf implementation + +On the proto files, we will use the following notation to refer to the `AttestationRequestI` defined above: + +```protobuf +google.protobuf.Any attestation = 1 + [ (cosmos_proto.accepts_interface) = "AttestationRequestI" ]; +``` + +This allows us to query for the attestations using nonces without worrying about the underlying implementation. + +For example: + +```protobuf +message QueryAttestationRequestByNonceRequest { uint64 nonce = 1; } + +message QueryAttestationRequestByNonceResponse { + google.protobuf.Any attestation = 1 + [ (cosmos_proto.accepts_interface) = "AttestationRequestI" ]; +} +``` + +And, implement the query as follows: + +```go +func (k Keeper) AttestationRequestByNonce( + ctx context.Context, + request *types.QueryAttestationRequestByNonceRequest, +) (*types.QueryAttestationRequestByNonceResponse, error) { + attestation, found, err := k.GetAttestationByNonce( + sdk.UnwrapSDKContext(ctx), + request.Nonce, + ) + if err != nil { + return nil, err + } + if !found { + return &types.QueryAttestationRequestByNonceResponse{}, types.ErrAttestationNotFound + } + val, err := codectypes.NewAnyWithValue(attestation) + if err != nil { + return nil, err + } + return &types.QueryAttestationRequestByNonceResponse{ + Attestation: val, + }, nil +} +``` + +#### State machine + +On the state machine, we will need to store the attestations when needed. To do so, we will define the following: + +##### Store latest nonce + +We will need to keep track of the latest nonce to enforce the nonces order and avoid overwriting existing attestations. This will be done using the following: + +```go +func (k Keeper) SetLatestAttestationNonce(ctx sdk.Context, nonce uint64) { + if k.CheckLatestAttestationNonce(ctx) && k.GetLatestAttestationNonce(ctx)+1 != nonce { + panic("not incrementing latest attestation nonce correctly!") + } + + store := ctx.KVStore(k.storeKey) + store.Set([]byte(types.LatestAttestationtNonce), types.UInt64Bytes(nonce)) +} +``` + +This will **panic** in the following cases: + +- The nonce we are incrementing does not exist. The following method checks its existence: + +```go +func (k Keeper) CheckLatestAttestationNonce(ctx sdk.Context) bool { + store := ctx.KVStore(k.storeKey) + has := store.Has([]byte(types.LatestAttestationtNonce)) + return has +} +``` + +- The provided nonce is different than `Latest nonce + 1`. + +##### Store attestation + +The following will store the attestation given that the nonce has never been used before. If not, the state machine will **panic**: + +```go +func (k Keeper) StoreAttestation(ctx sdk.Context, at types.AttestationRequestI) { + nonce := at.GetNonce() + key := []byte(types.GetAttestationKey(nonce)) + store := ctx.KVStore(k.storeKey) + + if store.Has(key) { + panic("trying to overwrite existing attestation request") + } + + b, err := k.cdc.MarshalInterface(at) + if err != nil { + panic(err) + } + store.Set((key), b) +} +``` + +The `GetAttestationKey(nonce)` will return the key used to store the attestation, which is defined as follows: + +```go +// AttestationRequestKey indexes valset requests by nonce +AttestationRequestKey = "AttestationRequestKey" + +// GetAttestationKey returns the following key format +// prefix nonce +// [0x0][0 0 0 0 0 0 0 1] +func GetAttestationKey(nonce uint64) string { + return AttestationRequestKey + string(UInt64Bytes(nonce)) +} +``` + +Also, we will define a `SetAttestationRequest` method that will take an attestation and store it while also updating the `LatestAttestationNonce` and emitting an event. This will allow us to always update the nonce and not forget about it: + +```go +func (k Keeper) SetAttestationRequest(ctx sdk.Context, at types.AttestationRequestI) error { + k.StoreAttestation(ctx, at) + k.SetLatestAttestationNonce(ctx, at.GetNonce()) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeAttestationRequest, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + sdk.NewAttribute(types.AttributeKeyNonce, fmt.Sprint(at.GetNonce())), + ), + ) + return nil +} +``` + +Then, defining eventual getters that will be used to serve orchestrator/relayer queries. + +### ABCI + +In order for the attestations requests to be stored correctly, we will need to enforce some rules that will define how these former will be handled. Thus, we will use `EndBlock` to check the state machine and see whether we need to create new attestations or not. + +To do so, we will define a custom `EndBlocker` that will be executed at the end of every block: + +```go +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + handleDataCommitmentRequest(ctx, k) + handleValsetRequest(ctx, k) +} +``` + +#### handleDataCommitmentRequest + +Handling the data commitment requests is fairly easy. We just check whether we reached a new data commitment window and we need to create a new data commitment request. + +The data commitment window is defined as a parameter: + +```protobuf +message Params { + ... + uint64 data_commitment_window = 1; +} +``` + +And set during genesis. + +So, we will have the following: + +```go +func handleDataCommitmentRequest(ctx sdk.Context, k keeper.Keeper) { + if ctx.BlockHeight() != 0 && ctx.BlockHeight()%int64(k.GetDataCommitmentWindowParam(ctx)) == 0 { + dataCommitment, err := k.GetCurrentDataCommitment(ctx) + if err != nil { + panic(sdkerrors.Wrap(err, "couldn't get current data commitment")) + } + err = k.SetAttestationRequest(ctx, &dataCommitment) + if err != nil { + panic(err) + } + } +} +``` + +Which will get the current data commitment as follows: + +```go +func (k Keeper) GetCurrentDataCommitment(ctx sdk.Context) (types.DataCommitment, error) { + beginBlock := uint64(ctx.BlockHeight()) - k.GetDataCommitmentWindowParam(ctx) + endBlock := uint64(ctx.BlockHeight()) + nonce := k.GetLatestAttestationNonce(ctx) + 1 + + dataCommitment := types.NewDataCommitment(nonce, beginBlock, endBlock) + return *dataCommitment, nil +} +``` + +And store it. + +#### handleValsetRequest + +The `handleValsetRequest` is more involved as it has more criteria to create new valsets: + +```go +func handleValsetRequest(ctx sdk.Context, k keeper.Keeper) { + // get the last valsets to compare against + var latestValset *types.Valset + if k.CheckLatestAttestationNonce(ctx) && k.GetLatestAttestationNonce(ctx) != 0 { + var err error + latestValset, err = k.GetLatestValset(ctx) + if err != nil { + panic(err) + } + } + + lastUnbondingHeight := k.GetLastUnBondingBlockHeight(ctx) + + significantPowerDiff := false + if latestValset != nil { + vs, err := k.GetCurrentValset(ctx) + if err != nil { + // this condition should only occur in the simulator + // ref : https://github.com/Gravity-Bridge/Gravity-Bridge/issues/35 + if errors.Is(err, types.ErrNoValidators) { + ctx.Logger().Error("no bonded validators", + "cause", err.Error(), + ) + return + } + panic(err) + } + intCurrMembers, err := types.BridgeValidators(vs.Members).ToInternal() + if err != nil { + panic(sdkerrors.Wrap(err, "invalid current valset members")) + } + intLatestMembers, err := types.BridgeValidators(latestValset.Members).ToInternal() + if err != nil { + panic(sdkerrors.Wrap(err, "invalid latest valset members")) + } + + significantPowerDiff = intCurrMembers.PowerDiff(*intLatestMembers) > 0.05 + } + + if (latestValset == nil) || (lastUnbondingHeight == uint64(ctx.BlockHeight())) || significantPowerDiff { + // if the conditions are true, put in a new validator set request to be signed and submitted to Ethereum + valset, err := k.GetCurrentValset(ctx) + if err != nil { + panic(err) + } + err = k.SetAttestationRequest(ctx, &valset) + if err != nil { + panic(err) + } + } +} +``` + +In a nutshell, a new valset will be emitted if any of the following is true: + +- The block is the genesis block and no previous valsets were defined. Then, a new valset will be stored referencing the validator set defined in genesis. +- We're at an unbonding height and we need to update the valset not to end up with a valset containing validators that will cease to exist. +- A significant power difference occured, i.e. the validator set changed significantly. This is defined using the following: + +```go +significantPowerDiff = intCurrMembers.PowerDiff(*intLatestMembers) > 0.05 +``` + +## Status + +Accepted + +## References + +- Tracker issue for the tasks [here](https://github.com/celestiaorg/celestia-app/issues/467). diff --git a/docs/architecture/ADR-005-QGB_reduce_state_usage.md b/docs/architecture/ADR-005-QGB_reduce_state_usage.md new file mode 100644 index 0000000000..3c2a86501a --- /dev/null +++ b/docs/architecture/ADR-005-QGB_reduce_state_usage.md @@ -0,0 +1,116 @@ +# ADR 5: Reduce QGB state usage + +## Context + +The first design for the QGB was to use the state extensively to store all the QGB related data: Attestations, `Valset Confirms` and `DataCommitment Confirms`. +As a direct consequence of this, we needed to add thorough checks on the state machine level to be sure that any proposed attestation is correct and will eventually be relayed to the target EVM chain. +The following issue lists these checks: [QGB data commitments/valsets state machine checks #631](https://github.com/celestiaorg/celestia-app/issues/631) and here is their [implementation](https://github.com/celestiaorg/celestia-app/blob/d63b99891023d153ea5937e4f3c1907a784654d8/x/qgb/keeper/msg_server.go#L28-L262). +Also, the state machine for the QGB module became complex and more prone to bugs that might end up halting/forking the chain. + +In addition to this, with the gas leak issue discussed in this [comment](https://github.com/celestiaorg/celestia-app/issues/631#issuecomment-1220848130), we ended up removing the sanitizing checks we used to run on the submitted `Valset Confirms` and `DataCommitment Confirms`. +This was done with the goal of not charging orchestrators increasing gas fees for every posted attestation. +A simple benchmark showed that the gas usage multiplied 2 times from `~50 000` to `100 000` after submitting 16 attestation. +Also, even if removing the checks was the most practical solution, it ended up opening new attack vectors on the QGB module state, such as flooding the network with incorrect attestations from users who are not even validators. Which would increase the burden on validators to handle all of that state. +Furthermore, it put the responsibility on the relayer to cherry-pick the right confirms from the invalid ones. + +We propose to keep the `Valset Confirms` and `DataCommitment Confirms` transaction types, but not handle/save them on the state. Instead, keep them as transactions in the blocks. And, delegate the task of parsing to the Relayer. This would allow us to achieve the following: + +- Reduce the state machine complexity. +- Reduce the amount of state used by the QGB. +- Prepare for a more Rollup oriented QGB design (tbd). + +## Alternative Approaches + +### Keep the existing design + +Keeping the current design would entail using the state extensively. +This proves bad when the state grows after a few hundred attestations, and performing checks on the `Valset Confirms` and `DataCommitment Confirms`, which run queries on the state, becomes too expensive. +An example of such issue in here: [QGB data commitments/valsets state machine checks #631](https://github.com/celestiaorg/celestia-app/issues/631) and [Investigate the QGB transactions cost #603](https://github.com/celestiaorg/celestia-app/issues/603). + +The approach that we were planning to take is to prune the state after the unbonding period. +This way, we will always have a fixed sized state, issue defining this: [Prune the QGB state after the unbonding period ends #309](https://github.com/celestiaorg/celestia-app/issues/309). + +### Separate P2P network + +This would mean gossiping the confirms and attestations in a separate P2P network. +The pros of this approach are that it will be cheaper and wouldn't involve any state changes. +However, slashing will be very difficult especially for liveness, i.e. an orchestrator not signing an attestation then slash them after a certain period. + +### Dump the QGB state in a namespace + +Remove the `MsgValsetConfirm` defined in [here](https://github.com/celestiaorg/celestia-app/blob/a965914b8a467f0384b17d9a8a0bb1ac62f384db/proto/qgb/msgs.proto#L24-L49) +And also, the `MsgDataCommitmentConfirm` defined in [here]( +https://github.com/celestiaorg/celestia-app/blob/a965914b8a467f0384b17d9a8a0bb1ac62f384db/proto/qgb/msgs.proto#L55-L76). +Which were the way orchestrators were able to post confirms to the QGB module. +Then, keep only the state that is created in [EndBlocker](https://github.com/celestiaorg/celestia-app/blob/a965914b8a467f0384b17d9a8a0bb1ac62f384db/x/qgb/abci.go#L12-L16). +Which are `Attestations`, i.e. `Valset`s and `DataCommitmentRequest`s. + +### QGB Rollup + +Deploy the QGB as a Rollup that posts its data to Celestia, and, uses a separate settlement layer for slashing. +This might be the end goal of the QGB, but it will be very involved to build at this stage. + +Also, if this ADR got accepted, it will be an important stepping stone in the Rollup direction. + +## Decision + +We will need to decide on two things: + +- [ ] Should we go for this approach? +- [ ] Should this change be part of QGB 1.0? +- [ ] When do we want to implement slashing? + +## Detailed Design + +The proposed design consists of keeping the same transaction types we currently have : the `MsgValsetConfirm` defined in [here](https://github.com/celestiaorg/celestia-app/blob/a965914b8a467f0384b17d9a8a0bb1ac62f384db/proto/qgb/msgs.proto#L24-L49), and the `MsgDataCommitmentConfirm` defined in [here]( +https://github.com/celestiaorg/celestia-app/blob/a965914b8a467f0384b17d9a8a0bb1ac62f384db/proto/qgb/msgs.proto#L55-L76). However, remove all the message server checks defined in the [msg_server.go](https://github.com/celestiaorg/celestia-app/blob/qgb-integration/x/qgb/keeper/msg_server.go) : + +```go +// ValsetConfirm handles MsgValsetConfirm. +func (k msgServer) ValsetConfirm( + c context.Context, + msg *types.MsgValsetConfirm, +) (*types.MsgValsetConfirmResponse, error) { + // +} + +// DataCommitmentConfirm handles MsgDataCommitmentConfirm. +func (k msgServer) DataCommitmentConfirm( + c context.Context, + msg *types.MsgDataCommitmentConfirm, +) (*types.MsgDataCommitmentConfirmResponse, error) { + // +} +``` + +This would reduce significantly the QGB module state usage, reduce the complexity of the state machine and give us the same benefits of the current design. + +As a direct consequence to this, the relayer will need to adapt to this change and start getting the transactions straight from the blocks, parse them and sanitize the commits. Thus, making the relayer implementation more complex. + +However, we can assume that the relayer will have enough computing power to do the latter. Also, only one relayer is necessary to have a working QGB contract. So, the relayer cost is justified. + +For the orchestrators, they will also need to parse the history to keep track of any missed signatures. But, same as with the relayers, the cost is justified. + +For posting transactions, we will rely on gas fees as a mechanism to limit malicious parties to flood the network with invalid transactions. Then, eventually slash malicious behavious. However, since posting confirms will be possible for any user of the network. It won't be possible to slash ordinary users, who are not running validators, if they post invalid confirms. + +When it comes to slashing, we can add the `dataRoot` of the blocks to state during `ProcessProposal`, `FinalizeCommit`, or in some other way to be defined. Then, we will have a way to slash orchestrators after a certain period of time if they didn't post any confirms. The exact details of this will be left for another ADR. + +## Status + +Proposed + +## Consequences + +### Positive + +- Reduce significantly the gas fees paid by orchestrators. +- Reduce significantly the use of Celestia state. + +### Negative + +- Reducing the checks applied on the confirms: everyone will be able to post commitments, and we will have no way to sanitize them. +- Potentially harder slashing as fraud proofs will need data from blocks and also state, compared to depending only on state for verification. + +### Neutral + +Credits to @evan-forbes. diff --git a/go.mod b/go.mod index 45e5d1acf8..21b02bf6c1 100644 --- a/go.mod +++ b/go.mod @@ -4,15 +4,18 @@ go 1.18 require ( github.com/celestiaorg/nmt v0.10.0 - github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20220418184507-c53157dd63f6 + github.com/celestiaorg/quantum-gravity-bridge v1.2.0 + github.com/cosmos/cosmos-sdk v0.46.0 + github.com/ethereum/go-ethereum v1.10.17 github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.2 + github.com/google/uuid v1.3.0 // indirect github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/pkg/errors v0.9.1 // indirect github.com/spf13/cast v1.5.0 github.com/spf13/cobra v1.5.0 github.com/stretchr/testify v1.8.0 - github.com/tendermint/tendermint v0.34.20 github.com/tendermint/tm-db v0.6.7 golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 // indirect @@ -24,7 +27,10 @@ require ( require ( cosmossdk.io/errors v1.0.0-beta.7 + cosmossdk.io/math v1.0.0-beta.2 github.com/celestiaorg/rsmt2d v0.6.0 + github.com/regen-network/cosmos-proto v0.3.1 + github.com/tendermint/tendermint v0.34.20 ) require ( @@ -32,11 +38,11 @@ require ( cloud.google.com/go/compute v1.6.1 // indirect cloud.google.com/go/iam v0.3.0 // indirect cloud.google.com/go/storage v1.14.0 // indirect - cosmossdk.io/math v1.0.0-beta.2 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/StackExchange/wmi v1.2.1 // indirect github.com/Workiva/go-datastructures v1.0.53 // indirect github.com/armon/go-metrics v0.4.0 // indirect github.com/aws/aws-sdk-go v1.40.45 // indirect @@ -53,6 +59,7 @@ require ( github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect github.com/confio/ics23/go v0.7.0 // indirect + github.com/containerd/continuity v0.1.0 // indirect github.com/cosmos/btcutil v1.0.4 // indirect github.com/cosmos/cosmos-proto v1.0.0-alpha7 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect @@ -64,20 +71,22 @@ require ( github.com/creachadair/taskgroup v0.3.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect + github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect - github.com/ethereum/go-ethereum v1.10.17 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/gin-gonic/gin v1.7.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/gateway v1.1.0 // indirect github.com/golang/glog v1.0.0 // indirect @@ -110,18 +119,20 @@ require ( github.com/magiconair/properties v1.8.6 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/onsi/ginkgo v1.16.4 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.2 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.12.2 // indirect github.com/prometheus/client_model v0.2.0 // indirect @@ -129,11 +140,11 @@ require ( github.com/prometheus/procfs v0.7.3 // indirect github.com/rakyll/statik v0.1.7 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect - github.com/regen-network/cosmos-proto v0.3.1 // indirect - github.com/rogpeppe/go-internal v1.8.1 // indirect + github.com/rjeczalik/notify v0.9.1 // indirect github.com/rs/cors v1.8.2 // indirect github.com/rs/zerolog v1.27.0 // indirect github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect + github.com/shirou/gopsutil v3.21.6+incompatible // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -143,6 +154,8 @@ require ( github.com/tendermint/btcd v0.1.1 // indirect github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect github.com/ulikunitz/xz v0.5.8 // indirect github.com/vivint/infectious v0.0.0-20200605153912-25a574ae18a3 // indirect github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect @@ -155,6 +168,7 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/ini.v1 v1.66.6 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect nhooyr.io/websocket v1.8.6 // indirect diff --git a/go.sum b/go.sum index 463c17bdb2..bf6e5b4cb5 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -93,6 +94,9 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= @@ -184,6 +188,8 @@ github.com/celestiaorg/merkletree v0.0.0-20210714075610-a84dc3ddbbe4 h1:CJdIpo8n github.com/celestiaorg/merkletree v0.0.0-20210714075610-a84dc3ddbbe4/go.mod h1:fzuHnhzj1pUygGz+1ZkB3uQbEUL4htqCGJ4Qs2LwMZA= github.com/celestiaorg/nmt v0.10.0 h1:HLfVWvpagHz5+uiE0QSjzv350wLhhnybNmrxq9NHLKc= github.com/celestiaorg/nmt v0.10.0/go.mod h1:3bqzTj8xKj0DgQUpOgZzoxvtNkC3MS/hTbQ6dn8SIa0= +github.com/celestiaorg/quantum-gravity-bridge v1.2.0 h1:l/LEEUP+x8MhhXB8rrWkyUVFZgQj1Ur/TAwUpnyLK38= +github.com/celestiaorg/quantum-gravity-bridge v1.2.0/go.mod h1:6WOajINTDEUXpSj5UZzod16UZ96ZVB/rFNKyM+Mt1gI= github.com/celestiaorg/rsmt2d v0.6.0 h1:32Eq5t7lPNbhftPFFjxwCUeEjWg/yGgeMbshxnGw03c= github.com/celestiaorg/rsmt2d v0.6.0/go.mod h1:EZ+O2KdCq8xI7WFwjATLdhtMdrdClmAs2w7zENDr010= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= @@ -192,6 +198,7 @@ github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -229,13 +236,17 @@ github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/ github.com/consensys/bavard v0.1.8-0.20210915155054-088da2f7f54a/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= github.com/consensys/gnark-crypto v0.5.3/go.mod h1:hOdPlWQV1gDLp7faZVeg8Y0iEPFaOUnCc4XeCCk96p0= -github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 h1:NmTXa/uVnDyp0TY5MKi197+3HWcnYWfnHGyaFthlnGw= +github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44= github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU= github.com/cosmos/cosmos-proto v1.0.0-alpha7 h1:yqYUOHF2jopwZh4dVQp3xgqwftE5/2hkrwIV6vkUbO0= @@ -255,6 +266,7 @@ github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6p github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM= github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk= @@ -268,6 +280,7 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= @@ -299,14 +312,16 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac h1:opbrjaN/L8gg6Xh5D04Tem+8xVcz6ajZlGCs49mQgyg= +github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -368,6 +383,9 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -381,6 +399,7 @@ github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= @@ -403,6 +422,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -495,6 +515,8 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -513,17 +535,20 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -575,7 +600,9 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU= github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3/go.mod h1:5PC6ZNPde8bBqU/ewGZig35+UIZtw9Ytxez8/q5ZyFE= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= @@ -695,13 +722,17 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -752,6 +783,7 @@ github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtb github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -765,8 +797,10 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= @@ -798,7 +832,6 @@ github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -811,6 +844,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= @@ -828,6 +862,7 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= @@ -840,6 +875,7 @@ github.com/prometheus/common v0.34.0 h1:RBmGO9d/FVjqHT0yUGQwBJhkwKV+wPCn7KGpvfab github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -847,6 +883,7 @@ github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= @@ -858,12 +895,14 @@ github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNw github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= @@ -883,6 +922,8 @@ github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfP github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.6+incompatible h1:mmZtAlWSd8U2HeRTjswbnDLPxqsEoK01NK+GZ1P+nEM= +github.com/shirou/gopsutil v3.21.6+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -904,6 +945,7 @@ github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= @@ -914,6 +956,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= @@ -955,12 +998,18 @@ github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp1 github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -995,6 +1044,7 @@ gitlab.com/NebulousLabs/errors v0.0.0-20171229012116-7ead97ef90b8/go.mod h1:ZkMZ gitlab.com/NebulousLabs/errors v0.0.0-20200929122200-06c536cf6975 h1:L/ENs/Ar1bFzUeKx6m3XjlmBgIUlykX9dzvp5k9NGxc= gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 h1:dizWJqTWjwyD8KGcMOwgrkqu1JIkofYgKkmDeNE7oAs= gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40/go.mod h1:rOnSnoRyxMI3fe/7KIbVcsHRGxe30OONv8dEgo+vCfA= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -1099,6 +1149,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1203,6 +1254,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1584,6 +1636,7 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= diff --git a/proto/qgb/genesis.proto b/proto/qgb/genesis.proto index b21513621a..8a909405dd 100644 --- a/proto/qgb/genesis.proto +++ b/proto/qgb/genesis.proto @@ -1,7 +1,19 @@ syntax = "proto3"; package qgb; +import "gogoproto/gogo.proto"; +import "qgb/types.proto"; +import "qgb/msgs.proto"; + option go_package = "github.com/celestiaorg/celestia-app/x/qgb/types"; -// GenesisState defines the capability module's genesis state. -message GenesisState {} +// Params represent the Quantum Gravity Bridge genesis and store parameters. +message Params { + option (gogoproto.stringer) = false; + + uint64 data_commitment_window = 1; +} + +// GenesisState struct, containing all persistant data required by the Gravity +// module +message GenesisState { Params params = 1; } diff --git a/proto/qgb/msgs.proto b/proto/qgb/msgs.proto index acefffa1a6..455e51f2cc 100644 --- a/proto/qgb/msgs.proto +++ b/proto/qgb/msgs.proto @@ -8,12 +8,15 @@ option go_package = "github.com/celestiaorg/celestia-app/x/qgb/types"; // Msg defines the state transitions possible for QGB service Msg { - // ValsetConfirm allows the validators to submit their signatures over the validator set. + // ValsetConfirm allows the validators to submit their signatures over the + // validator set. rpc ValsetConfirm(MsgValsetConfirm) returns (MsgValsetConfirmResponse) { option (google.api.http).post = "/qgb/valset_confirm"; } - // DataCommitmentConfirm allows the validators to submit a confirmation for a data commitment. - rpc DataCommitmentConfirm(MsgDataCommitmentConfirm) returns (MsgDataCommitmentConfirmResponse) { + // DataCommitmentConfirm allows the validators to submit a confirmation for a + // data commitment. + rpc DataCommitmentConfirm(MsgDataCommitmentConfirm) + returns (MsgDataCommitmentConfirmResponse) { option (google.api.http).post = "/qgb/data_commitment_confirm"; } } @@ -34,10 +37,15 @@ service Msg { // chain store and submit them to Ethereum to update the validator set // ------------- message MsgValsetConfirm { - uint64 nonce = 1; + // Universal nonce referencing the `ValSet`. + uint64 nonce = 1; + // Orchestrator `celes1` account address. string orchestrator = 2; - string eth_address = 3; - string signature = 4; + // Ethereum address, associated to the orchestrator, used to sign the `ValSet` + // message. + string eth_address = 3; + // The `ValSet` message signature. + string signature = 4; } // MsgValsetConfirmResponse describes the response returned after the submission @@ -45,7 +53,27 @@ message MsgValsetConfirm { message MsgValsetConfirmResponse {} // MsgDataCommitmentConfirm describes a data commitment for a set of blocks. -message MsgDataCommitmentConfirm {} +message MsgDataCommitmentConfirm { + // Universal nonce referencing the Data Commitment. + uint64 nonce = 1; + // Signature over the commitment, the range of blocks, the validator address + // and the Ethereum address. + string signature = 2; + // Orchestrator account address who will be signing the message. + string validator_address = 3; + // Hex `0x` encoded Ethereum public key that will be used by this validator on + // Ethereum. + string eth_address = 4; + // Merkle root over a merkle tree containing the data roots of a set of + // blocks. + string commitment = 5; + // First block defining the ordered set of blocks used to create the + // commitment. + uint64 begin_block = 6; + // Last block defining the ordered set of blocks used to create the + // commitment. + uint64 end_block = 7; +} // MsgValsetConfirmResponse describes the response returned after the submission // of a MsgDataCommitmentConfirm. diff --git a/proto/qgb/query.proto b/proto/qgb/query.proto index 4fc8500dc7..b5e3b8da15 100644 --- a/proto/qgb/query.proto +++ b/proto/qgb/query.proto @@ -1,12 +1,81 @@ syntax = "proto3"; package qgb; +import "qgb/genesis.proto"; +import "qgb/types.proto"; import "google/api/annotations.proto"; import "cosmos/base/query/v1beta1/pagination.proto"; +import "qgb/msgs.proto"; +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "google/protobuf/any.proto"; option go_package = "github.com/celestiaorg/celestia-app/x/qgb/types"; // Query defines the gRPC querier service. service Query { + // Params queries the current parameters for the qgb module + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/qgb/params"; + } + + // queries for attestations requests waiting to be signed by an orchestrator + + // AttestationRequestByNonce queries attestation request by nonce. + // Returns nil if not found. + rpc AttestationRequestByNonce(QueryAttestationRequestByNonceRequest) + returns (QueryAttestationRequestByNonceResponse) { + option (google.api.http).get = "/qgb/attestations/requests/{nonce}"; + } + // LatestAttestationNonce queries latest attestation nonce. + rpc LatestAttestationNonce(QueryLatestAttestationNonceRequest) + returns (QueryLatestAttestationNonceResponse) { + option (google.api.http).get = "/qgb/attestations/nonce/latest"; + } + + // misc + + // LastUnbondingHeight returns the last unbonding height + rpc LastUnbondingHeight(QueryLastUnbondingHeightRequest) + returns (QueryLastUnbondingHeightResponse) { + option (google.api.http).get = "/qgb/unbonding"; + } } +// QueryParamsRequest +message QueryParamsRequest {} +// QueryParamsResponse +message QueryParamsResponse { + Params params = 1 [ (gogoproto.nullable) = false ]; +} + +// QueryAttestationRequestByNonceRequest +message QueryAttestationRequestByNonceRequest { uint64 nonce = 1; } + +// QueryAttestationRequestByNonceResponse +message QueryAttestationRequestByNonceResponse { + // AttestationRequestI is either a Data Commitment or a Valset. + // This was decided as part of the universal nonce approach under: + // https://github.com/celestiaorg/celestia-app/issues/468#issuecomment-1156887715 + google.protobuf.Any attestation = 1 + [ (cosmos_proto.accepts_interface) = "AttestationRequestI" ]; +} + +// QueryLatestAttestationNonceRequest latest attestation nonce request +message QueryLatestAttestationNonceRequest {} +// QueryLatestAttestationNonceResponse latest attestation nonce response +message QueryLatestAttestationNonceResponse { uint64 nonce = 1; } + +// QueryLastValsetRequestBeforeNonceRequest last Valset request before universal +// nonce request +message QueryLastValsetRequestBeforeNonceRequest { uint64 nonce = 1; } + +// QueryLastValsetRequestBeforeNonceResponse last Valset request before height +// response +message QueryLastValsetRequestBeforeNonceResponse { Valset valset = 1; } + +// QueryLastUnbondingHeightRequest +message QueryLastUnbondingHeightRequest {} + +// QueryLastUnbondingHeightResponse +message QueryLastUnbondingHeightResponse { uint64 height = 1; } diff --git a/proto/qgb/types.proto b/proto/qgb/types.proto new file mode 100644 index 0000000000..53f51818b7 --- /dev/null +++ b/proto/qgb/types.proto @@ -0,0 +1,47 @@ +syntax = "proto3"; +package qgb; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/celestiaorg/celestia-app/x/qgb/types"; + +// BridgeValidator represents a validator's ETH address and its power +message BridgeValidator { + // Voting power of the validator. + uint64 power = 1; + // Ethereum address that will be used by the validator to sign messages. + string ethereum_address = 2; +} + +// Valset is the Ethereum Bridge Multsig Set, each qgb validator also +// maintains an ETH key to sign messages, these are used to check signatures on +// ETH because of the significant gas savings +message Valset { + option (cosmos_proto.implements_interface) = "AttestationRequestI"; + // Universal nonce defined under: + // https://github.com/celestiaorg/celestia-app/pull/464 + uint64 nonce = 1; + // List of BridgeValidator containing the current validator set. + repeated BridgeValidator members = 2 [ (gogoproto.nullable) = false ]; + // Current chain height + uint64 height = 3; +} + +// DataCommitment is the data commitment request message that will be signed +// using orchestrators. +// It does not contain a `commitment` field as this message will be created +// inside the state machine and it doesn't make sense to ask tendermint for the +// commitment there. +message DataCommitment { + option (cosmos_proto.implements_interface) = "AttestationRequestI"; + // Universal nonce defined under: + // https://github.com/celestiaorg/celestia-app/pull/464 + uint64 nonce = 1; + // First block defining the ordered set of blocks used to create the + // commitment. + uint64 begin_block = 2; + // Last block defining the ordered set of blocks used to create the + // commitment. + uint64 end_block = 3; +} diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index 9b2e548041..3d2f937082 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -7,8 +7,6 @@ protoc_gen_gocosmos() { echo -e "\tPlease run this command from somewhere inside the cosmos-sdk folder." return 1 fi - - go get github.com/regen-network/cosmos-proto/protoc-gen-gocosmos@latest 2>/dev/null } protoc_gen_gocosmos @@ -25,6 +23,11 @@ done cd .. +# temporary import hack to use cosmos-sdk implementation of Any type. +# check https://github.com/celestiaorg/celestia-app/issues/507 for more information. +sed -i 's/types "github.com\/celestiaorg\/celestia-app\/codec\/types"/types "github.com\/cosmos\/cosmos-sdk\/codec\/types"/g' \ + github.com/celestiaorg/celestia-app/x/qgb/types/query.pb.go + # move proto files to the right places cp -r github.com/celestiaorg/celestia-app/* ./ rm -rf github.com diff --git a/scripts/single-node.sh b/scripts/single-node.sh index 62e956979b..5b1ac36925 100755 --- a/scripts/single-node.sh +++ b/scripts/single-node.sh @@ -10,7 +10,13 @@ celestia-appd init $CHAINID --chain-id $CHAINID celestia-appd keys add validator --keyring-backend="test" # this won't work because the some proto types are decalared twice and the logs output to stdout (dependency hell involving iavl) celestia-appd add-genesis-account $(celestia-appd keys show validator -a --keyring-backend="test") $coins -celestia-appd gentx validator 5000000000utia --keyring-backend="test" --chain-id $CHAINID +celestia-appd gentx validator 5000000000utia \ + --keyring-backend="test" \ + --chain-id $CHAINID \ + --orchestrator-address $(celestia-appd keys show validator -a --keyring-backend="test") \ + #da6ed55cb2894ac2c9c10209c09de8e8b9d109b910338d5bf3d747a7e1fc9eb9 + --ethereum-address 0x966e6f22781EF6a6A82BBB4DB3df8E225DfD9488 + celestia-appd collect-gentxs # Set proper defaults and change ports diff --git a/testutil/common.go b/testutil/common.go new file mode 100644 index 0000000000..9ef631c021 --- /dev/null +++ b/testutil/common.go @@ -0,0 +1,500 @@ +package testutil + +import ( + "bytes" + "testing" + "time" + + cosmosmath "cosmossdk.io/math" + "github.com/celestiaorg/celestia-app/app" + "github.com/celestiaorg/celestia-app/x/qgb/keeper" + "github.com/celestiaorg/celestia-app/x/qgb/types" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + ccodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + ccrypto "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/std" + "github.com/cosmos/cosmos-sdk/store" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/distribution" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/params" + paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/cosmos/cosmos-sdk/x/staking" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmversion "github.com/tendermint/tendermint/proto/tendermint/version" + dbm "github.com/tendermint/tm-db" +) + +var ( + // ModuleBasics is a mock module basic manager for testing + ModuleBasics = app.ModuleBasics + // TestingStakeParams is a set of staking params for testing + TestingStakeParams = stakingtypes.Params{ + UnbondingTime: 100, + MaxValidators: 10, + MaxEntries: 10, + HistoricalEntries: 10000, + BondDenom: "stake", + MinCommissionRate: sdk.NewDecWithPrec(0, 0), + } + + // ConsPrivKeys generate ed25519 ConsPrivKeys to be used for validator operator keys + ConsPrivKeys = []ccrypto.PrivKey{ + ed25519.GenPrivKey(), + ed25519.GenPrivKey(), + ed25519.GenPrivKey(), + ed25519.GenPrivKey(), + ed25519.GenPrivKey(), + } + + // ConsPubKeys holds the consensus public keys to be used for validator operator keys + ConsPubKeys = []ccrypto.PubKey{ + ConsPrivKeys[0].PubKey(), + ConsPrivKeys[1].PubKey(), + ConsPrivKeys[2].PubKey(), + ConsPrivKeys[3].PubKey(), + ConsPrivKeys[4].PubKey(), + } + + // AccPrivKeys generate secp256k1 pubkeys to be used for account pub keys + AccPrivKeys = []ccrypto.PrivKey{ + secp256k1.GenPrivKey(), + secp256k1.GenPrivKey(), + secp256k1.GenPrivKey(), + secp256k1.GenPrivKey(), + secp256k1.GenPrivKey(), + } + + // AccPubKeys holds the pub keys for the account keys + AccPubKeys = []ccrypto.PubKey{ + AccPrivKeys[0].PubKey(), + AccPrivKeys[1].PubKey(), + AccPrivKeys[2].PubKey(), + AccPrivKeys[3].PubKey(), + AccPrivKeys[4].PubKey(), + } + + // AccAddrs holds the sdk.AccAddresses + AccAddrs = []sdk.AccAddress{ + sdk.AccAddress(AccPubKeys[0].Address()), + sdk.AccAddress(AccPubKeys[1].Address()), + sdk.AccAddress(AccPubKeys[2].Address()), + sdk.AccAddress(AccPubKeys[3].Address()), + sdk.AccAddress(AccPubKeys[4].Address()), + } + + // ValAddrs holds the sdk.ValAddresses + ValAddrs = []sdk.ValAddress{ + sdk.ValAddress(AccPubKeys[0].Address()), + sdk.ValAddress(AccPubKeys[1].Address()), + sdk.ValAddress(AccPubKeys[2].Address()), + sdk.ValAddress(AccPubKeys[3].Address()), + sdk.ValAddress(AccPubKeys[4].Address()), + } + + // OrchPubKeys holds the pub keys for the orchestrator + OrchPubKeys = []ccrypto.PubKey{ + OrchPrivKeys[0].PubKey(), + OrchPrivKeys[1].PubKey(), + OrchPrivKeys[2].PubKey(), + OrchPrivKeys[3].PubKey(), + OrchPrivKeys[4].PubKey(), + } + + // OrchPrivKeys Orchestrator private keys + OrchPrivKeys = []ccrypto.PrivKey{ + secp256k1.GenPrivKey(), + secp256k1.GenPrivKey(), + secp256k1.GenPrivKey(), + secp256k1.GenPrivKey(), + secp256k1.GenPrivKey(), + } + + // OrchAddrs AccAddrs holds the sdk.AccAddresses + OrchAddrs = []sdk.AccAddress{ + sdk.AccAddress(OrchPubKeys[0].Address()), + sdk.AccAddress(OrchPubKeys[1].Address()), + sdk.AccAddress(OrchPubKeys[2].Address()), + sdk.AccAddress(OrchPubKeys[3].Address()), + sdk.AccAddress(OrchPubKeys[4].Address()), + } + + // EthAddrs holds etheruem addresses + EthAddrs = initEthAddrs(1000000) // TODO update 1000000 with a more realistic value + + // InitTokens holds the number of tokens to initialize an account with + InitTokens = sdk.TokensFromConsensusPower(110, sdk.DefaultPowerReduction) + + // InitCoins holds the number of coins to initialize an account with + InitCoins = sdk.NewCoins(sdk.NewCoin(TestingStakeParams.BondDenom, InitTokens)) + + // StakingAmount holds the staking power to start a validator with + StakingAmount = sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) +) + +func initEthAddrs(count int) []gethcommon.Address { + addresses := make([]gethcommon.Address, count) + for i := 0; i < count; i++ { + ethAddr := gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(i + 1)}, 20)) + addresses[i] = ethAddr + } + return addresses +} + +// TestInput stores the various keepers required to test gravity +type TestInput struct { + QgbKeeper *keeper.Keeper + AccountKeeper authkeeper.AccountKeeper + StakingKeeper stakingkeeper.Keeper + SlashingKeeper slashingkeeper.Keeper + DistKeeper distrkeeper.Keeper + BankKeeper bankkeeper.BaseKeeper + Context sdk.Context + Marshaler codec.Codec + LegacyAmino *codec.LegacyAmino +} + +// CreateTestEnv creates the keeper testing environment for gravity +func CreateTestEnv(t *testing.T) TestInput { + t.Helper() + + // Initialize store keys + qgbKey := sdk.NewKVStoreKey(types.StoreKey) + keyAcc := sdk.NewKVStoreKey(authtypes.StoreKey) + keyStaking := sdk.NewKVStoreKey(stakingtypes.StoreKey) + keyBank := sdk.NewKVStoreKey(banktypes.StoreKey) + keyDistro := sdk.NewKVStoreKey(distrtypes.StoreKey) + keyParams := sdk.NewKVStoreKey(paramstypes.StoreKey) + tkeyParams := sdk.NewTransientStoreKey(paramstypes.TStoreKey) + keySlashing := sdk.NewKVStoreKey(slashingtypes.StoreKey) + + // Initialize memory database and mount stores on it + db := dbm.NewMemDB() + ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(qgbKey, storetypes.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyAcc, storetypes.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyParams, storetypes.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyStaking, storetypes.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyBank, storetypes.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyDistro, storetypes.StoreTypeIAVL, db) + ms.MountStoreWithDB(tkeyParams, storetypes.StoreTypeTransient, db) + ms.MountStoreWithDB(keySlashing, storetypes.StoreTypeIAVL, db) + err := ms.LoadLatestVersion() + require.Nil(t, err) + + // Create sdk.Context + ctx := sdk.NewContext(ms, tmproto.Header{ + Version: tmversion.Consensus{ + Block: 0, + App: 0, + }, + ChainID: "", + Height: 1234567, + Time: time.Date(2020, time.April, 22, 12, 0, 0, 0, time.UTC), + LastBlockId: tmproto.BlockID{ + Hash: []byte{}, + PartSetHeader: tmproto.PartSetHeader{ + Total: 0, + Hash: []byte{}, + }, + }, + LastCommitHash: []byte{}, + DataHash: []byte{}, + ValidatorsHash: []byte{}, + NextValidatorsHash: []byte{}, + ConsensusHash: []byte{}, + AppHash: []byte{}, + LastResultsHash: []byte{}, + EvidenceHash: []byte{}, + ProposerAddress: []byte{}, + }, false, log.TestingLogger()) + + cdc := MakeTestCodec() + marshaler := MakeTestMarshaler() + + paramsKeeper := paramskeeper.NewKeeper(marshaler, cdc, keyParams, tkeyParams) + paramsKeeper.Subspace(authtypes.ModuleName) + paramsKeeper.Subspace(banktypes.ModuleName) + paramsKeeper.Subspace(stakingtypes.ModuleName) + paramsKeeper.Subspace(distrtypes.ModuleName) + paramsKeeper.Subspace(types.DefaultParamspace) + paramsKeeper.Subspace(slashingtypes.ModuleName) + + // this is also used to initialize module accounts for all the map keys + maccPerms := map[string][]string{ + authtypes.FeeCollectorName: nil, + distrtypes.ModuleName: nil, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + types.ModuleName: {authtypes.Minter, authtypes.Burner}, + } + + accountKeeper := authkeeper.NewAccountKeeper( + marshaler, + keyAcc, // target store + getSubspace(paramsKeeper, authtypes.ModuleName), + authtypes.ProtoBaseAccount, // prototype + maccPerms, + app.Bech32PrefixAccAddr, + ) + + blockedAddr := make(map[string]bool, len(maccPerms)) + for acc := range maccPerms { + blockedAddr[authtypes.NewModuleAddress(acc).String()] = true + } + bankKeeper := bankkeeper.NewBaseKeeper( + marshaler, + keyBank, + accountKeeper, + getSubspace(paramsKeeper, banktypes.ModuleName), + blockedAddr, + ) + bankKeeper.SetParams( + ctx, + banktypes.Params{ + SendEnabled: []*banktypes.SendEnabled{}, + DefaultSendEnabled: true, + }, + ) + + stakingKeeper := stakingkeeper.NewKeeper(marshaler, keyStaking, accountKeeper, bankKeeper, getSubspace(paramsKeeper, stakingtypes.ModuleName)) + stakingKeeper.SetParams(ctx, TestingStakeParams) + + distKeeper := distrkeeper.NewKeeper(marshaler, keyDistro, getSubspace(paramsKeeper, distrtypes.ModuleName), accountKeeper, bankKeeper, stakingKeeper, authtypes.FeeCollectorName) + distKeeper.SetParams(ctx, distrtypes.DefaultParams()) + + // set genesis items required for distribution + distKeeper.SetFeePool(ctx, distrtypes.InitialFeePool()) + + // total supply to track this + totalSupply := sdk.NewCoins(sdk.NewInt64Coin("stake", 100000000)) + + // set up initial accounts + for name, perms := range maccPerms { + mod := authtypes.NewEmptyModuleAccount(name, perms...) + if name == stakingtypes.NotBondedPoolName { + err = bankKeeper.MintCoins(ctx, types.ModuleName, totalSupply) + require.NoError(t, err) + err = bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, mod.Name, totalSupply) + require.NoError(t, err) + } else if name == distrtypes.ModuleName { + // some big pot to pay out + amt := sdk.NewCoins(sdk.NewInt64Coin("stake", 500000)) + err = bankKeeper.MintCoins(ctx, types.ModuleName, amt) + require.NoError(t, err) + err = bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, mod.Name, amt) + require.NoError(t, err) + } + accountKeeper.SetModuleAccount(ctx, mod) + } + + stakeAddr := authtypes.NewModuleAddress(stakingtypes.BondedPoolName) + moduleAcct := accountKeeper.GetAccount(ctx, stakeAddr) + require.NotNil(t, moduleAcct) + + slashingKeeper := slashingkeeper.NewKeeper( + marshaler, + keySlashing, + &stakingKeeper, + getSubspace(paramsKeeper, slashingtypes.ModuleName).WithKeyTable(slashingtypes.ParamKeyTable()), + ) + + k := keeper.NewKeeper(marshaler, qgbKey, getSubspace(paramsKeeper, types.DefaultParamspace), &stakingKeeper) + testQGBParams := types.DefaultGenesis().Params + k.SetParams(ctx, *testQGBParams) + + k.SetLatestAttestationNonce(ctx, 0) + + stakingKeeper = *stakingKeeper.SetHooks( + stakingtypes.NewMultiStakingHooks( + distKeeper.Hooks(), + slashingKeeper.Hooks(), + k.Hooks(), + ), + ) + + return TestInput{ + QgbKeeper: k, + AccountKeeper: accountKeeper, + BankKeeper: bankKeeper, + StakingKeeper: stakingKeeper, + SlashingKeeper: slashingKeeper, + DistKeeper: distKeeper, + Context: ctx, + Marshaler: marshaler, + LegacyAmino: cdc, + } +} + +// MakeTestCodec creates a legacy amino codec for testing +func MakeTestCodec() *codec.LegacyAmino { + cdc := codec.NewLegacyAmino() + auth.AppModuleBasic{}.RegisterLegacyAminoCodec(cdc) + bank.AppModuleBasic{}.RegisterLegacyAminoCodec(cdc) + staking.AppModuleBasic{}.RegisterLegacyAminoCodec(cdc) + distribution.AppModuleBasic{}.RegisterLegacyAminoCodec(cdc) + sdk.RegisterLegacyAminoCodec(cdc) + ccodec.RegisterCrypto(cdc) + params.AppModuleBasic{}.RegisterLegacyAminoCodec(cdc) + types.RegisterCodec(cdc) + return cdc +} + +// getSubspace returns a param subspace for a given module name. +func getSubspace(k paramskeeper.Keeper, moduleName string) paramstypes.Subspace { + subspace, _ := k.GetSubspace(moduleName) + return subspace +} + +// MakeTestMarshaler creates a proto codec for use in testing +func MakeTestMarshaler() codec.Codec { + interfaceRegistry := codectypes.NewInterfaceRegistry() + std.RegisterInterfaces(interfaceRegistry) + ModuleBasics.RegisterInterfaces(interfaceRegistry) + types.RegisterInterfaces(interfaceRegistry) + return codec.NewProtoCodec(interfaceRegistry) +} + +// SetupFiveValChain does all the initialization for a 5 Validator chain using the keys here +func SetupFiveValChain(t *testing.T) (TestInput, sdk.Context) { + t.Helper() + input := CreateTestEnv(t) + + // Set the params for our modules + input.StakingKeeper.SetParams(input.Context, TestingStakeParams) + + // Initialize each of the validators + msgServer := stakingkeeper.NewMsgServerImpl(input.StakingKeeper) + for i := range []int{0, 1, 2, 3, 4} { + + // Initialize the account for the key + acc := input.AccountKeeper.NewAccount( + input.Context, + authtypes.NewBaseAccount(AccAddrs[i], AccPubKeys[i], uint64(i), 0), + ) + + // Set the balance for the account + require.NoError(t, input.BankKeeper.MintCoins(input.Context, types.ModuleName, InitCoins)) + // nolint + input.BankKeeper.SendCoinsFromModuleToAccount(input.Context, types.ModuleName, acc.GetAddress(), InitCoins) + + // Set the account in state + input.AccountKeeper.SetAccount(input.Context, acc) + + // Create a validator for that account using some tokens in the account + // and the staking handler + _, err := msgServer.CreateValidator(input.Context, NewTestMsgCreateValidator(ValAddrs[i], ConsPubKeys[i], StakingAmount, OrchAddrs[i], EthAddrs[i])) + + // Return error if one exists + require.NoError(t, err) + } + + // Run the staking endblocker to ensure valset is correct in state + staking.EndBlocker(input.Context, input.StakingKeeper) + + // Return the test input + return input, input.Context +} + +func NewTestMsgCreateValidator( + address sdk.ValAddress, + pubKey ccrypto.PubKey, + amt cosmosmath.Int, + orchAddr sdk.AccAddress, + ethAddr gethcommon.Address, +) *stakingtypes.MsgCreateValidator { + commission := stakingtypes.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) + out, err := stakingtypes.NewMsgCreateValidator( + address, pubKey, sdk.NewCoin("stake", amt), + stakingtypes.Description{ + Moniker: "", + Identity: "", + Website: "", + SecurityContact: "", + Details: "", + }, commission, sdk.OneInt(), + orchAddr, ethAddr, + ) + if err != nil { + panic(err) + } + return out +} + +// SetupTestChain sets up a test environment with the provided validator voting weights +func SetupTestChain(t *testing.T, weights []uint64) (TestInput, sdk.Context) { + t.Helper() + input := CreateTestEnv(t) + + // Set the params for our modules + TestingStakeParams.MaxValidators = 100 + input.StakingKeeper.SetParams(input.Context, TestingStakeParams) + + // Initialize each of the validators + msgServer := stakingkeeper.NewMsgServerImpl(input.StakingKeeper) + for i, weight := range weights { + consPrivKey := ed25519.GenPrivKey() + consPubKey := consPrivKey.PubKey() + valPrivKey := secp256k1.GenPrivKey() + valPubKey := valPrivKey.PubKey() + valAddr := sdk.ValAddress(valPubKey.Address()) + accAddr := sdk.AccAddress(valPubKey.Address()) + + // Initialize the account for the key + acc := input.AccountKeeper.NewAccount( + input.Context, + authtypes.NewBaseAccount(accAddr, valPubKey, uint64(i), 0), + ) + + // Set the balance for the account + weightCoins := sdk.NewCoins(sdk.NewInt64Coin(TestingStakeParams.BondDenom, int64(weight))) + require.NoError(t, input.BankKeeper.MintCoins(input.Context, types.ModuleName, weightCoins)) + require.NoError(t, input.BankKeeper.SendCoinsFromModuleToAccount(input.Context, types.ModuleName, accAddr, weightCoins)) + + // Set the account in state + input.AccountKeeper.SetAccount(input.Context, acc) + + // Create a validator for that account using some of the tokens in the account + // and the staking handler + _, err := msgServer.CreateValidator( + input.Context, + NewTestMsgCreateValidator(valAddr, consPubKey, sdk.NewIntFromUint64(weight), accAddr, EthAddrs[i]), + ) + require.NoError(t, err) + + // Run the staking endblocker to ensure valset is correct in state + staking.EndBlocker(input.Context, input.StakingKeeper) + } + + // some inputs can cause the validator creation not to work, this checks that + // everything was successful + validators := input.StakingKeeper.GetBondedValidatorsByPower(input.Context) + require.Equal(t, len(weights), len(validators)) + + // Return the test input + return input, input.Context +} + +func NewTestMsgUnDelegateValidator(address sdk.ValAddress, amt cosmosmath.Int) *stakingtypes.MsgUndelegate { + msg := stakingtypes.NewMsgUndelegate(sdk.AccAddress(address), address, sdk.NewCoin("stake", amt)) + return msg +} diff --git a/testutil/test_app.go b/testutil/test_app.go index 1ae2d66c0a..f6f55624a1 100644 --- a/testutil/test_app.go +++ b/testutil/test_app.go @@ -188,7 +188,7 @@ func generateKeyring(t *testing.T, cdc codec.Codec, accts ...string) keyring.Key } } - _, err := kb.NewAccount(testAccName, testMnemo, "1234", "", hd.Secp256k1) + _, err := kb.NewAccount(TestAccName, testMnemo, "1234", "", hd.Secp256k1) if err != nil { panic(err) } @@ -300,7 +300,7 @@ func GenerateKeyringSigner(t *testing.T, acct string) *types.KeyringSigner { const ( // nolint:lll testMnemo = `ramp soldier connect gadget domain mutual staff unusual first midnight iron good deputy wage vehicle mutual spike unlock rocket delay hundred script tumble choose` - testAccName = "test-account" + TestAccName = "test-account" testChainID = "test-chain-1" ) diff --git a/x/payment/types/builder.go b/x/payment/types/builder.go index 6d043af38b..e03b3204de 100644 --- a/x/payment/types/builder.go +++ b/x/payment/types/builder.go @@ -41,7 +41,7 @@ func NewKeyringSigner(ring keyring.Keyring, name string, chainID string) *Keyrin // QueryAccountNumber queries the application to find the latest account number and // sequence, updating the respective internal fields. The internal account number must // be set by this method or by manually calling k.SetAccountNumber in order for any built -// transactions to be valide +// transactions to be valid func (k *KeyringSigner) QueryAccountNumber(ctx context.Context, conn *grpc.ClientConn) error { info, err := k.Key(k.keyringAccName) if err != nil { diff --git a/x/qgb/abci.go b/x/qgb/abci.go new file mode 100644 index 0000000000..6c8a190c20 --- /dev/null +++ b/x/qgb/abci.go @@ -0,0 +1,85 @@ +package qgb + +import ( + "errors" + + "github.com/celestiaorg/celestia-app/x/qgb/keeper" + "github.com/celestiaorg/celestia-app/x/qgb/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// SignificantPowerDifferenceThreshold the threshold of change in the validator set power +// that would need the creation of a new valset request. +const SignificantPowerDifferenceThreshold = 0.05 + +// EndBlocker is called at the end of every block. +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + handleDataCommitmentRequest(ctx, k) + handleValsetRequest(ctx, k) +} + +func handleDataCommitmentRequest(ctx sdk.Context, k keeper.Keeper) { + if ctx.BlockHeight() != 0 && ctx.BlockHeight()%int64(k.GetDataCommitmentWindowParam(ctx)) == 0 { + dataCommitment, err := k.GetCurrentDataCommitment(ctx) + if err != nil { + panic(sdkerrors.Wrap(err, "coudln't get current data commitment")) + } + err = k.SetAttestationRequest(ctx, &dataCommitment) + if err != nil { + panic(err) + } + } +} + +func handleValsetRequest(ctx sdk.Context, k keeper.Keeper) { + // get the last valsets to compare against + var latestValset *types.Valset + if k.CheckLatestAttestationNonce(ctx) && k.GetLatestAttestationNonce(ctx) != 0 { + var err error + latestValset, err = k.GetLatestValset(ctx) + if err != nil { + panic(err) + } + } + + lastUnbondingHeight := k.GetLastUnBondingBlockHeight(ctx) + + significantPowerDiff := false + if latestValset != nil { + vs, err := k.GetCurrentValset(ctx) + if err != nil { + // this condition should only occur in the simulator + // ref : https://github.com/Gravity-Bridge/Gravity-Bridge/issues/35 + if errors.Is(err, types.ErrNoValidators) { + ctx.Logger().Error("no bonded validators", + "cause", err.Error(), + ) + return + } + panic(err) + } + intCurrMembers, err := types.BridgeValidators(vs.Members).ToInternal() + if err != nil { + panic(sdkerrors.Wrap(err, "invalid current valset members")) + } + intLatestMembers, err := types.BridgeValidators(latestValset.Members).ToInternal() + if err != nil { + panic(sdkerrors.Wrap(err, "invalid latest valset members")) + } + + significantPowerDiff = intCurrMembers.PowerDiff(*intLatestMembers) > SignificantPowerDifferenceThreshold + } + + if (latestValset == nil) || (lastUnbondingHeight == uint64(ctx.BlockHeight())) || significantPowerDiff { + // if the conditions are true, put in a new validator set request to be signed and submitted to Ethereum + valset, err := k.GetCurrentValset(ctx) + if err != nil { + panic(err) + } + err = k.SetAttestationRequest(ctx, &valset) + if err != nil { + panic(err) + } + } +} diff --git a/x/qgb/abci_test.go b/x/qgb/abci_test.go new file mode 100644 index 0000000000..da10fe9f6a --- /dev/null +++ b/x/qgb/abci_test.go @@ -0,0 +1,86 @@ +package qgb_test + +import ( + "testing" + + "github.com/celestiaorg/celestia-app/testutil" + "github.com/celestiaorg/celestia-app/x/qgb" + "github.com/celestiaorg/celestia-app/x/qgb/types" + "github.com/cosmos/cosmos-sdk/x/staking" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestAttestationCreationWhenStartingTheChain(t *testing.T) { + input, ctx := testutil.SetupFiveValChain(t) + pk := input.QgbKeeper + + // EndBlocker should set a new validator set if not available + qgb.EndBlocker(ctx, *pk) + require.Equal(t, uint64(1), pk.GetLatestAttestationNonce(ctx)) + attestation, found, err := pk.GetAttestationByNonce(ctx, 1) + require.True(t, found) + require.Nil(t, err) + require.NotNil(t, attestation) + require.Equal(t, uint64(1), attestation.GetNonce()) +} + +func TestValsetCreationUponUnbonding(t *testing.T) { + input, ctx := testutil.SetupFiveValChain(t) + pk := input.QgbKeeper + + currentValsetNonce := pk.GetLatestAttestationNonce(ctx) + vs, err := pk.GetCurrentValset(ctx) + require.Nil(t, err) + err = pk.SetAttestationRequest(ctx, &vs) + require.Nil(t, err) + + input.Context = ctx.WithBlockHeight(ctx.BlockHeight() + 1) + // begin unbonding + msgServer := stakingkeeper.NewMsgServerImpl(input.StakingKeeper) + undelegateMsg := testutil.NewTestMsgUnDelegateValidator(testutil.ValAddrs[0], testutil.StakingAmount) + _, err = msgServer.Undelegate(input.Context, undelegateMsg) + require.NoError(t, err) + + // Run the staking endblocker to ensure valset is set in state + staking.EndBlocker(input.Context, input.StakingKeeper) + qgb.EndBlocker(input.Context, *pk) + + assert.NotEqual(t, currentValsetNonce, pk.GetLatestAttestationNonce(ctx)) +} + +func TestValsetEmission(t *testing.T) { + input, ctx := testutil.SetupFiveValChain(t) + pk := input.QgbKeeper + + // EndBlocker should set a new validator set + qgb.EndBlocker(ctx, *pk) + + require.Equal(t, uint64(1), pk.GetLatestAttestationNonce(ctx)) + attestation, found, err := pk.GetAttestationByNonce(ctx, 1) + require.Nil(t, err) + require.True(t, found) + require.NotNil(t, attestation) + require.Equal(t, uint64(1), attestation.GetNonce()) + + // get the valsets + require.Equal(t, types.ValsetRequestType, attestation.Type()) + vs, ok := attestation.(*types.Valset) + require.True(t, ok) + require.NotNil(t, vs) +} + +func TestValsetSetting(t *testing.T) { + input, ctx := testutil.SetupFiveValChain(t) + pk := input.QgbKeeper + + vs, err := pk.GetCurrentValset(ctx) + require.Nil(t, err) + err = pk.SetAttestationRequest(ctx, &vs) + require.Nil(t, err) + + require.Equal(t, uint64(1), pk.GetLatestAttestationNonce(ctx)) +} + +// Add data commitment window tests diff --git a/x/qgb/client/cli/datacommitment.go b/x/qgb/client/cli/datacommitment.go deleted file mode 100644 index a399dbf9b3..0000000000 --- a/x/qgb/client/cli/datacommitment.go +++ /dev/null @@ -1,21 +0,0 @@ -package cli - -import ( - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/spf13/cobra" -) - -func CmdGetDataCommitmentConfirm() *cobra.Command { - //nolint: exhaustivestruct - cmd := &cobra.Command{ - Use: "datacommitment-confirm // TODO", - Short: "Get data commitment // TODO", - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - // TODO - return nil - }, - } - flags.AddQueryFlagsToCmd(cmd) - return cmd -} diff --git a/x/qgb/client/cli/valsetconfirm.go b/x/qgb/client/cli/valsetconfirm.go deleted file mode 100644 index b2b29967d1..0000000000 --- a/x/qgb/client/cli/valsetconfirm.go +++ /dev/null @@ -1,21 +0,0 @@ -package cli - -import ( - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/spf13/cobra" -) - -func CmdGetValsetConfirm() *cobra.Command { - //nolint: exhaustivestruct - cmd := &cobra.Command{ - Use: "valset-confirm [nonce] [bech32 validator address]", - Short: "Get valset confirmation with a particular nonce from a particular validator", - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - // TODO - return nil - }, - } - flags.AddQueryFlagsToCmd(cmd) - return cmd -} diff --git a/x/qgb/genesis.go b/x/qgb/genesis.go index 530e842f76..3b417d3ec1 100644 --- a/x/qgb/genesis.go +++ b/x/qgb/genesis.go @@ -9,11 +9,13 @@ import ( // InitGenesis initializes the capability module's state from a provided genesis // state. func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { + k.SetLatestAttestationNonce(ctx, 0) + k.SetParams(ctx, *genState.Params) } // ExportGenesis returns the capability module's exported genesis. func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { genesis := types.DefaultGenesis() - + genesis.Params.DataCommitmentWindow = k.GetDataCommitmentWindowParam(ctx) return genesis } diff --git a/x/qgb/handler.go b/x/qgb/handler.go index f8b59b3148..a89ce12fc3 100644 --- a/x/qgb/handler.go +++ b/x/qgb/handler.go @@ -9,7 +9,8 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// NewHandler uses the provided qgb keeper to create an sdk.Handler +// Can be deleted after implementing the Orchestrator and Relayer as per QGB ADR-005. +// NewHandler uses the provided qgb keeper to create an sdk.Handler. func NewHandler(k keeper.Keeper) sdk.Handler { msgServer := keeper.NewMsgServerImpl(k) diff --git a/x/qgb/keeper/hooks.go b/x/qgb/keeper/hooks.go new file mode 100644 index 0000000000..e68e625da1 --- /dev/null +++ b/x/qgb/keeper/hooks.go @@ -0,0 +1,70 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Hooks is a wrapper struct around Keeper. +type Hooks struct { + k Keeper +} + +// Create new gravity hooks +func (k Keeper) Hooks() Hooks { + // if startup is mis-ordered in app.go this hook will halt + // the chain when called. Keep this check to make such a mistake + // obvious + if k.storeKey == nil { + panic("hooks initialized before GravityKeeper") + } + return Hooks{k} +} + +func (h Hooks) AfterValidatorBeginUnbonding(ctx sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error { + // When Validator starts Unbonding, Persist the block height in the store + // Later in endblocker, check if there is at least one validator who started unbonding and create a valset request. + // The reason for creating valset requests in endblock is to create only one valset request per block, + // if multiple validators starts unbonding at same block. + + // this hook IS called for jailing or unbonding triggered by users but it IS NOT called for jailing triggered + // in the endblocker therefore we call the keeper function ourselves there. + + h.k.SetLastUnBondingBlockHeight(ctx, uint64(ctx.BlockHeight())) + return nil +} + +func (h Hooks) BeforeDelegationCreated(_ sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { + return nil +} + +func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error { + return nil +} + +func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) error { + return nil +} + +func (h Hooks) AfterValidatorBonded(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error { + return nil +} + +func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error { + return nil +} + +func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) error { + return nil +} + +func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) error { + return nil +} + +func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { + return nil +} + +func (h Hooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { + return nil +} diff --git a/x/qgb/keeper/keeper.go b/x/qgb/keeper/keeper.go index dbc113c142..83bf2c9dda 100644 --- a/x/qgb/keeper/keeper.go +++ b/x/qgb/keeper/keeper.go @@ -1,30 +1,79 @@ package keeper import ( + "encoding/binary" "fmt" - - storetypes "github.com/cosmos/cosmos-sdk/store/types" - "github.com/tendermint/tendermint/libs/log" + "time" "github.com/celestiaorg/celestia-app/x/qgb/types" "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/common" + "github.com/tendermint/tendermint/libs/log" ) type Keeper struct { - cdc codec.BinaryCodec - storeKey storetypes.StoreKey - memKey storetypes.StoreKey + cdc codec.BinaryCodec + storeKey storetypes.StoreKey + paramSpace paramtypes.Subspace + + StakingKeeper StakingKeeper } -func NewKeeper(cdc codec.BinaryCodec, storeKey, memKey storetypes.StoreKey) *Keeper { +func NewKeeper(cdc codec.BinaryCodec, storeKey storetypes.StoreKey, paramSpace paramtypes.Subspace, stakingKeeper StakingKeeper) *Keeper { + // set KeyTable if it has not already been set + if !paramSpace.HasKeyTable() { + paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) + } + return &Keeper{ - cdc: cdc, - storeKey: storeKey, - memKey: memKey, + cdc: cdc, + storeKey: storeKey, + StakingKeeper: stakingKeeper, + paramSpace: paramSpace, } } +// GetParams returns the parameters from the store +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + k.paramSpace.GetParamSet(ctx, ¶ms) + return +} + +// SetParams sets the parameters in the store +func (k Keeper) SetParams(ctx sdk.Context, ps types.Params) { + k.paramSpace.SetParamSet(ctx, &ps) +} + +// DeserializeValidatorIterator returns validators from the validator iterator. +// Adding here in gravity keeper as cdc is not available inside endblocker. +func (k Keeper) DeserializeValidatorIterator(vals []byte) stakingtypes.ValAddresses { + validators := stakingtypes.ValAddresses{ + Addresses: []string{}, + } + k.cdc.MustUnmarshal(vals, &validators) + return validators +} + +// StakingKeeper restricts the functionality of the bank keeper used in the payment keeper +type StakingKeeper interface { + GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool) + GetBondedValidatorsByPower(ctx sdk.Context) []stakingtypes.Validator + GetLastValidatorPower(ctx sdk.Context, valAddr sdk.ValAddress) int64 + GetParams(ctx sdk.Context) stakingtypes.Params + ValidatorQueueIterator(ctx sdk.Context, endTime time.Time, endHeight int64) sdk.Iterator + GetValidatorByOrchestrator(ctx sdk.Context, addr sdk.AccAddress) (validator stakingtypes.Validator, found bool) + GetValidatorByEthereumAddress(ctx sdk.Context, addr common.Address) (validator stakingtypes.Validator, found bool) +} + func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) } + +// UInt64FromBytes create uint from binary big endian representation. +func UInt64FromBytes(s []byte) uint64 { + return binary.BigEndian.Uint64(s) +} diff --git a/x/qgb/keeper/keeper_attestation.go b/x/qgb/keeper/keeper_attestation.go new file mode 100644 index 0000000000..2ca2e49a83 --- /dev/null +++ b/x/qgb/keeper/keeper_attestation.go @@ -0,0 +1,94 @@ +package keeper + +import ( + "fmt" + + "github.com/celestiaorg/celestia-app/x/qgb/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SetAttestationRequest sets a new attestation request to the store to be signed +// by orchestrators afterwards. +func (k Keeper) SetAttestationRequest(ctx sdk.Context, at types.AttestationRequestI) error { + k.StoreAttestation(ctx, at) + k.SetLatestAttestationNonce(ctx, at.GetNonce()) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeAttestationRequest, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + sdk.NewAttribute(types.AttributeKeyNonce, fmt.Sprint(at.GetNonce())), + ), + ) + return nil +} + +// StoreAttestation saves the attestation in store. +// Should panic if overwriting existing one. +func (k Keeper) StoreAttestation(ctx sdk.Context, at types.AttestationRequestI) { + nonce := at.GetNonce() + key := []byte(types.GetAttestationKey(nonce)) + store := ctx.KVStore(k.storeKey) + + if store.Has(key) { + panic("trying to overwrite existing attestation request") + } + + b, err := k.cdc.MarshalInterface(at) + if err != nil { + panic(err) + } + store.Set((key), b) +} + +// SetLatestAttestationNonce sets the latest attestation request nonce, since it's +// expected that this value will only increase by one and it panics otherwise. +func (k Keeper) SetLatestAttestationNonce(ctx sdk.Context, nonce uint64) { + // in case the latest attestation nonce doesn't exist, + // we proceed to initialize it in the store. + // however, if it already exists, we check if the nonce is correctly incremented. + if k.CheckLatestAttestationNonce(ctx) && k.GetLatestAttestationNonce(ctx)+1 != nonce { + panic("not incrementing latest attestation nonce correctly") + } + + store := ctx.KVStore(k.storeKey) + store.Set([]byte(types.LatestAttestationtNonce), types.UInt64Bytes(nonce)) +} + +// CheckLatestAttestationNonce returns true if the latest attestation request nonce +// is declared in the store and false if it has not been initialized. +func (k Keeper) CheckLatestAttestationNonce(ctx sdk.Context) bool { + store := ctx.KVStore(k.storeKey) + has := store.Has([]byte(types.LatestAttestationtNonce)) + return has +} + +// GetLatestAttestationNonce returns the latest attestation request nonce. +// Panics if the latest attestation nonce doesn't exit. Make sure to call `CheckLatestAttestationNonce` +// before getting the nonce. +// This value is set on chain startup, it shouldn't panic in normal conditions. +// Check x/qgb/genesis.go for more information. +func (k Keeper) GetLatestAttestationNonce(ctx sdk.Context) uint64 { + store := ctx.KVStore(k.storeKey) + bytes := store.Get([]byte(types.LatestAttestationtNonce)) + if bytes == nil { + panic("nil LatestAttestationNonce") + } + return UInt64FromBytes(bytes) +} + +// GetAttestationByNonce returns an attestation request by nonce. +// Returns (nil, false, nil) if the attestation is not found. +func (k Keeper) GetAttestationByNonce(ctx sdk.Context, nonce uint64) (types.AttestationRequestI, bool, error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get([]byte(types.GetAttestationKey(nonce))) + if bz == nil { + return nil, false, nil + } + var at types.AttestationRequestI + err := k.cdc.UnmarshalInterface(bz, &at) + if err != nil { + return nil, false, types.ErrUnmarshalllAttestation + } + return at, true, nil +} diff --git a/x/qgb/keeper/keeper_data_commitment.go b/x/qgb/keeper/keeper_data_commitment.go index 552cac92b1..269bfb8ec4 100644 --- a/x/qgb/keeper/keeper_data_commitment.go +++ b/x/qgb/keeper/keeper_data_commitment.go @@ -5,19 +5,23 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// GetDataCommitmentConfirm -func (k Keeper) GetDataCommitmentConfirm(ctx sdk.Context) *types.MsgDataCommitmentConfirm { - // TODO - return nil -} +// TODO add unit tests for all the keepers + +// GetCurrentDataCommitment creates latest data commitment at current height according to +// the data commitment window specified +func (k Keeper) GetCurrentDataCommitment(ctx sdk.Context) (types.DataCommitment, error) { + beginBlock := uint64(ctx.BlockHeight()) - k.GetDataCommitmentWindowParam(ctx) + endBlock := uint64(ctx.BlockHeight()) + nonce := k.GetLatestAttestationNonce(ctx) + 1 -// SetDataCommitmentConfirm -func (k Keeper) SetDataCommitmentConfirm(ctx sdk.Context, dcConf types.MsgDataCommitmentConfirm) []byte { - // TODO - return nil + dataCommitment := types.NewDataCommitment(nonce, beginBlock, endBlock) + return *dataCommitment, nil } -// DeleteDataCommitmentConfirms -func (k Keeper) DeleteDataCommitmentConfirms(ctx sdk.Context) { - // TODO +func (k Keeper) GetDataCommitmentWindowParam(ctx sdk.Context) uint64 { + resp, err := k.Params(sdk.WrapSDKContext(ctx), &types.QueryParamsRequest{}) + if err != nil { + panic(err) + } + return resp.Params.DataCommitmentWindow } diff --git a/x/qgb/keeper/keeper_valset.go b/x/qgb/keeper/keeper_valset.go index f548583b02..f5cb2d7358 100644 --- a/x/qgb/keeper/keeper_valset.go +++ b/x/qgb/keeper/keeper_valset.go @@ -1,30 +1,188 @@ package keeper import ( + "fmt" + "math/big" + + cosmosmath "cosmossdk.io/math" "github.com/celestiaorg/celestia-app/x/qgb/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdk "github.com/cosmos/cosmos-sdk/types" ) -// GetValsetConfirm -func (k Keeper) GetValsetConfirm(ctx sdk.Context, nonce uint64, validator sdk.AccAddress) *types.MsgValsetConfirm { - // TODO - return nil +// GetLatestValset returns the latest validator set in store. This is different +// from the CurrentValset because this one has been saved and is therefore *the* latest valset +// saved in store. GetCurrentValset shows you what could be, if you chose to save it, this function +// shows you what is the latest valset that was saved. +// Panics if no valset is found. Because, a valset is always created when starting +// the chain. Check x/qgb/abci.go:68 for more information. +func (k Keeper) GetLatestValset(ctx sdk.Context) (*types.Valset, error) { + nonce := k.GetLatestAttestationNonce(ctx) + for i := uint64(0); i <= nonce; i++ { + at, found, err := k.GetAttestationByNonce(ctx, nonce-i) + if err != nil { + return nil, err + } + if !found { + panic(sdkerrors.Wrap( + types.ErrNilAttestation, + fmt.Sprintf("stumbled upon nil attestation for nonce %d", i), + )) + } + if at.Type() == types.ValsetRequestType { + valset, ok := at.(*types.Valset) + if !ok { + return nil, sdkerrors.Wrap(types.ErrAttestationNotValsetRequest, "couldn't cast attestation to valset") + } + return valset, nil + } + } + // should never execute + panic(sdkerrors.Wrap(sdkerrors.ErrNotFound, "couldn't find latest valset")) } -// SetValsetConfirm -func (k Keeper) SetValsetConfirm(ctx sdk.Context, valsetConf types.MsgValsetConfirm) []byte { - // TODO - return nil +// SetLastUnBondingBlockHeight sets the last unbonding block height. Note this +// value is not saved to state or loaded at genesis. This value is reset to zero +// on chain upgrade. +func (k Keeper) SetLastUnBondingBlockHeight(ctx sdk.Context, unbondingBlockHeight uint64) { + store := ctx.KVStore(k.storeKey) + store.Set([]byte(types.LastUnBondingBlockHeight), types.UInt64Bytes(unbondingBlockHeight)) } -// GetValsetConfirms -func (k Keeper) GetValsetConfirms(ctx sdk.Context, nonce uint64) (confirms []types.MsgValsetConfirm) { - // TODO - return nil +// GetLastUnBondingBlockHeight returns the last unbonding block height or zero +// if not set. This value is not saved or loaded at genesis. This value is reset +// to zero on chain upgrade. +func (k Keeper) GetLastUnBondingBlockHeight(ctx sdk.Context) uint64 { + store := ctx.KVStore(k.storeKey) + bytes := store.Get([]byte(types.LastUnBondingBlockHeight)) + + if len(bytes) == 0 { + return 0 + } + return UInt64FromBytes(bytes) } -// DeleteValsetConfirms -func (k Keeper) DeleteValsetConfirms(ctx sdk.Context, nonce uint64) { - // TODO +func (k Keeper) GetCurrentValset(ctx sdk.Context) (types.Valset, error) { + validators := k.StakingKeeper.GetBondedValidatorsByPower(ctx) + if len(validators) == 0 { + return types.Valset{}, types.ErrNoValidators + } + // allocate enough space for all validators, but len zero, we then append + // so that we have an array with extra capacity but the correct length depending + // on how many validators have keys set. + bridgeValidators := make([]*types.InternalBridgeValidator, 0, len(validators)) + totalPower := sdk.NewInt(0) + // TODO someone with in depth info on Cosmos staking should determine + // if this is doing what I think it's doing + for _, validator := range validators { + val := validator.GetOperator() + if err := sdk.VerifyAddressFormat(val); err != nil { + return types.Valset{}, sdkerrors.Wrap(err, types.ErrInvalidValAddress.Error()) + } + + p := sdk.NewInt(k.StakingKeeper.GetLastValidatorPower(ctx, val)) + + // TODO make sure this is always the case + bv := types.BridgeValidator{Power: p.Uint64(), EthereumAddress: validator.EthAddress} + ibv, err := types.NewInternalBridgeValidator(bv) + if err != nil { + return types.Valset{}, sdkerrors.Wrapf(err, types.ErrInvalidEthAddress.Error(), val) + } + bridgeValidators = append(bridgeValidators, ibv) + totalPower = totalPower.Add(p) + } + // normalize power values to the maximum bridge power which is 2^32 + for i := range bridgeValidators { + bridgeValidators[i].Power = normalizeValidatorPower(bridgeValidators[i].Power, totalPower) + } + + // increment the nonce, since this potential future valset should be after the current valset + valsetNonce := k.GetLatestAttestationNonce(ctx) + 1 + + valset, err := types.NewValset(valsetNonce, uint64(ctx.BlockHeight()), bridgeValidators) + if err != nil { + return types.Valset{}, (sdkerrors.Wrap(err, types.ErrInvalidValset.Error())) + } + return *valset, nil +} + +// normalizeValidatorPower scales rawPower with respect to totalValidatorPower to take a value between 0 and 2^32 +// Uses BigInt operations to avoid overflow errors +// Example: rawPower = max (2^63 - 1), totalValidatorPower = 1 validator: (2^63 - 1) +// +// result: (2^63 - 1) * 2^32 / (2^63 - 1) = 2^32 = 4294967296 [this is the multiplier value below, our max output] +// +// Example: rawPower = max (2^63 - 1), totalValidatorPower = 1000 validators with the same power: 1000*(2^63 - 1) +// +// result: (2^63 - 1) * 2^32 / (1000(2^63 - 1)) = 2^32 / 1000 = 4294967 +func normalizeValidatorPower(rawPower uint64, totalValidatorPower cosmosmath.Int) uint64 { + // Compute rawPower * multiplier / quotient + // Set the upper limit to 2^32, which would happen if there is a single validator with all the power + multiplier := new(big.Int).SetUint64(4294967296) + // Scale by current validator powers, a particularly low-power validator (1 out of over 2^32) would have 0 power + quotient := new(big.Int).Set(totalValidatorPower.BigInt()) + power := new(big.Int).SetUint64(rawPower) + power.Mul(power, multiplier) + power.Quo(power, quotient) + return power.Uint64() +} + +// GetLastValsetBeforeNonce returns the previous valset before the provided `nonce`. +// the `nonce` can be a valset, but this method will return the valset before it. +// If the provided nonce is 1. It will return an error. Because, there is no valset before nonce 1. +func (k Keeper) GetLastValsetBeforeNonce(ctx sdk.Context, nonce uint64) (*types.Valset, error) { + if nonce == 1 { + return nil, types.ErrNoValsetBeforeNonceOne + } + if nonce > k.GetLatestAttestationNonce(ctx) { + return nil, types.ErrNonceHigherThanLatestAttestationNonce + } + // starting at 1 because the current nonce can be a valset + // and we need the previous one. + for i := uint64(1); i < nonce; i++ { + at, found, err := k.GetAttestationByNonce(ctx, nonce-i) + if err != nil { + return nil, err + } + if !found { + return nil, sdkerrors.Wrap( + types.ErrNilAttestation, + fmt.Sprintf("nonce=%d", nonce-i), + ) + } + if at.Type() == types.ValsetRequestType { + valset, ok := at.(*types.Valset) + if !ok { + return nil, sdkerrors.Wrap(types.ErrAttestationNotValsetRequest, "couldn't cast attestation to valset") + } + return valset, nil + } + } + return nil, sdkerrors.Wrap( + sdkerrors.ErrNotFound, + fmt.Sprintf("couldn't find valset before nonce %d", nonce), + ) +} + +// TODO add query for this method and make the orchestrator Querier use it. +// GetValsetByNonce returns the stored valset associated with the provided nonce. +// Returns (nil, false, nil) if not found. +func (k Keeper) GetValsetByNonce(ctx sdk.Context, nonce uint64) (*types.Valset, bool, error) { + at, found, err := k.GetAttestationByNonce(ctx, nonce) + if err != nil { + return nil, false, err + } + if !found { + return nil, false, nil + } + if at.Type() != types.ValsetRequestType { + return nil, false, sdkerrors.Wrap(types.ErrAttestationNotValsetRequest, "attestation is not a valset request") + } + + valset, ok := at.(*types.Valset) + if !ok { + return nil, false, sdkerrors.Wrap(types.ErrAttestationNotValsetRequest, "couldn't cast attestation to valset") + } + return valset, true, nil } diff --git a/x/qgb/keeper/keeper_valset_test.go b/x/qgb/keeper/keeper_valset_test.go new file mode 100644 index 0000000000..14ac954366 --- /dev/null +++ b/x/qgb/keeper/keeper_valset_test.go @@ -0,0 +1,65 @@ +package keeper_test + +import ( + "bytes" + "testing" + + "github.com/celestiaorg/celestia-app/testutil" + "github.com/celestiaorg/celestia-app/x/qgb/types" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// Test that valset creation produces the expected normalized power values. +func TestCurrentValsetNormalization(t *testing.T) { + // Setup the overflow test + maxPower64 := make([]uint64, 64) // users with max power (approx 2^63) + expPower64 := make([]uint64, 64) // expected scaled powers + ethAddrs64 := make([]gethcommon.Address, 64) // need 64 eth addresses for this test + for i := 0; i < 64; i++ { + maxPower64[i] = uint64(9223372036854775807) + expPower64[i] = 67108864 // 2^32 split amongst 64 validators + ethAddrs64[i] = gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(i + 1)}, 20)) + } + + // any lower than this and a validator won't be created + const minStake = 1000000 + + specs := map[string]struct { + srcPowers []uint64 + expPowers []uint64 + }{ + "one": { + srcPowers: []uint64{minStake}, + expPowers: []uint64{4294967296}, + }, + "two": { + srcPowers: []uint64{minStake * 99, minStake * 1}, + expPowers: []uint64{4252017623, 42949672}, + }, + "four equal": { + srcPowers: []uint64{minStake, minStake, minStake, minStake}, + expPowers: []uint64{1073741824, 1073741824, 1073741824, 1073741824}, + }, + "four equal max power": { + srcPowers: []uint64{4294967296, 4294967296, 4294967296, 4294967296}, + expPowers: []uint64{1073741824, 1073741824, 1073741824, 1073741824}, + }, + "overflow": { + srcPowers: maxPower64, + expPowers: expPower64, + }, + } + for msg, spec := range specs { + spec := spec + t.Run(msg, func(t *testing.T) { + input, ctx := testutil.SetupTestChain(t, spec.srcPowers) + r, err := input.QgbKeeper.GetCurrentValset(ctx) + require.NoError(t, err) + rMembers, err := types.BridgeValidators(r.Members).ToInternal() + require.NoError(t, err) + assert.Equal(t, spec.expPowers, rMembers.GetPowers()) + }) + } +} diff --git a/x/qgb/keeper/msg_server.go b/x/qgb/keeper/msg_server.go index c63cbf6065..398542917b 100644 --- a/x/qgb/keeper/msg_server.go +++ b/x/qgb/keeper/msg_server.go @@ -16,14 +16,20 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer { return &msgServer{Keeper: keeper} } -// ValsetConfirm handles MsgValsetConfirm -func (k msgServer) ValsetConfirm(c context.Context, msg *types.MsgValsetConfirm) (*types.MsgValsetConfirmResponse, error) { - // TODO +// ValsetConfirm handles MsgValsetConfirm. +func (k msgServer) ValsetConfirm( + _ context.Context, + _ *types.MsgValsetConfirm, +) (*types.MsgValsetConfirmResponse, error) { + // empty as per QGB ADR-005 return &types.MsgValsetConfirmResponse{}, nil } -// DataCommitmentConfirm handles MsgDataCommitmentConfirm -func (k msgServer) DataCommitmentConfirm(context.Context, *types.MsgDataCommitmentConfirm) (*types.MsgDataCommitmentConfirmResponse, error) { - // TODO +// DataCommitmentConfirm handles MsgDataCommitmentConfirm. +func (k msgServer) DataCommitmentConfirm( + _ context.Context, + _ *types.MsgDataCommitmentConfirm, +) (*types.MsgDataCommitmentConfirmResponse, error) { + // empty as per QGB ADR-005 return &types.MsgDataCommitmentConfirmResponse{}, nil } diff --git a/x/qgb/keeper/query_attestation.go b/x/qgb/keeper/query_attestation.go new file mode 100644 index 0000000000..38e8da5e5c --- /dev/null +++ b/x/qgb/keeper/query_attestation.go @@ -0,0 +1,42 @@ +package keeper + +import ( + "context" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + + "github.com/celestiaorg/celestia-app/x/qgb/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (k Keeper) AttestationRequestByNonce( + ctx context.Context, + request *types.QueryAttestationRequestByNonceRequest, +) (*types.QueryAttestationRequestByNonceResponse, error) { + attestation, found, err := k.GetAttestationByNonce( + sdk.UnwrapSDKContext(ctx), + request.Nonce, + ) + if err != nil { + return nil, err + } + if !found { + return &types.QueryAttestationRequestByNonceResponse{}, types.ErrAttestationNotFound + } + val, err := codectypes.NewAnyWithValue(attestation) + if err != nil { + return nil, err + } + return &types.QueryAttestationRequestByNonceResponse{ + Attestation: val, + }, nil +} + +func (k Keeper) LatestAttestationNonce( + ctx context.Context, + request *types.QueryLatestAttestationNonceRequest, +) (*types.QueryLatestAttestationNonceResponse, error) { + return &types.QueryLatestAttestationNonceResponse{ + Nonce: k.GetLatestAttestationNonce(sdk.UnwrapSDKContext(ctx)), + }, nil +} diff --git a/x/qgb/keeper/query_general.go b/x/qgb/keeper/query_general.go new file mode 100644 index 0000000000..d1bd323c7b --- /dev/null +++ b/x/qgb/keeper/query_general.go @@ -0,0 +1,25 @@ +package keeper + +import ( + "context" + + "github.com/celestiaorg/celestia-app/x/qgb/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// LastUnbondingHeight queries the last unbonding height. +func (k Keeper) LastUnbondingHeight( + c context.Context, + req *types.QueryLastUnbondingHeightRequest, +) (*types.QueryLastUnbondingHeightResponse, error) { + return &types.QueryLastUnbondingHeightResponse{ + Height: k.GetLastUnBondingBlockHeight(sdk.UnwrapSDKContext(c)), + }, nil +} + +func (k Keeper) Params(c context.Context, request *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + params := k.GetParams(sdk.UnwrapSDKContext(c)) + return &types.QueryParamsResponse{ + Params: params, + }, nil +} diff --git a/x/qgb/keeper/query_valset.go b/x/qgb/keeper/query_valset.go new file mode 100644 index 0000000000..56adea4ea1 --- /dev/null +++ b/x/qgb/keeper/query_valset.go @@ -0,0 +1,22 @@ +package keeper + +import ( + "context" + + "github.com/celestiaorg/celestia-app/x/qgb/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// TODO add unit tests for all of these requests + +// LastValsetRequestBeforeNonce queries the last valset request before nonce +func (k Keeper) LastValsetRequestBeforeNonce( + c context.Context, + req *types.QueryLastValsetRequestBeforeNonceRequest, +) (*types.QueryLastValsetRequestBeforeNonceResponse, error) { + vs, err := k.GetLastValsetBeforeNonce(sdk.UnwrapSDKContext(c), req.Nonce) + if err != nil { + return nil, err + } + return &types.QueryLastValsetRequestBeforeNonceResponse{Valset: vs}, nil +} diff --git a/x/qgb/module.go b/x/qgb/module.go index 8ec00efa08..6343915b11 100644 --- a/x/qgb/module.go +++ b/x/qgb/module.go @@ -50,7 +50,7 @@ func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { types.RegisterCodec(cdc) } -// RegisterInterfaces registers the module's interface types +// RegisterInterfaces registers the module's interface types. func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { types.RegisterInterfaces(reg) } @@ -79,13 +79,11 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *r // GetTxCmd returns the capability module's root tx command. func (a AppModuleBasic) GetTxCmd() *cobra.Command { - // TODO return nil } // GetQueryCmd returns the capability module's root query command. func (AppModuleBasic) GetQueryCmd() *cobra.Command { - // TODO return nil } @@ -128,6 +126,7 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd // RegisterServices registers a GRPC query service to respond to the // module-specific GRPC queries. func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) } @@ -160,6 +159,7 @@ func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} // EndBlock executes all ABCI EndBlock logic respective to the capability module. It // returns no validator updates. -func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { +func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + EndBlocker(ctx, am.keeper) return []abci.ValidatorUpdate{} } diff --git a/x/qgb/types/abi_consts.go b/x/qgb/types/abi_consts.go new file mode 100644 index 0000000000..8639b2b22f --- /dev/null +++ b/x/qgb/types/abi_consts.go @@ -0,0 +1,170 @@ +package types + +import ( + "log" + "strings" + + wrapper "github.com/celestiaorg/quantum-gravity-bridge/wrappers/QuantumGravityBridge.sol" + "github.com/ethereum/go-ethereum/accounts/abi" + ethcmn "github.com/ethereum/go-ethereum/common" +) + +const ( + // EthSignPrefix is used to mimic the expected encoding. see + // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/c9f328ef66251db7fac7c704dd6c5523fc53b0ab/contracts/cryptography/ECDSA.sol#L69-L82 //nolint:lll + EthSignPrefix = "\x19Ethereum Signed Message:\n32" + + // InternalQGBabiJSON is the json encoded abi for private functions in the + // qgb contract. This is needed to encode data that is signed over in a way + // that the contracts can easily verify. + InternalQGBabiJSON = `[ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "power", + "type": "uint256" + } + ], + "internalType": "struct Validator[]", + "name": "_validators", + "type": "tuple[]" + } + ], + "name": "computeValidatorSetHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_bridge_id", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_separator", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_dataRootTupleRoot", + "type": "bytes32" + } + ], + "name": "domainSeparateDataRootTupleRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_bridge_id", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_separator", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_powerThreshold", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_validatorSetHash", + "type": "bytes32" + } + ], + "name": "domainSeparateValidatorSetHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + } + ]` + + // Domain separator constants copied directly from the contracts. + ValidatorSetDomainSeparator = "0x636865636b706f696e7400000000000000000000000000000000000000000000" + DataCommitmentDomainSeparator = "0x7472616e73616374696f6e426174636800000000000000000000000000000000" +) + +var ( + ExternalQGBabi abi.ABI + InternalQGBabi abi.ABI + BridgeValidatorAbi abi.Arguments + + VsDomainSeparator ethcmn.Hash + DcDomainSeparator ethcmn.Hash + BridgeID = ethcmn.HexToHash("Evm_Celestia_Bridge") // TODO to be removed afterwards +) + +func init() { + contractAbi, err := abi.JSON(strings.NewReader(wrapper.QuantumGravityBridgeMetaData.ABI)) + if err != nil { + log.Fatalln("bad ABI constant", err) + } + ExternalQGBabi = contractAbi + + internalABI, err := abi.JSON(strings.NewReader(InternalQGBabiJSON)) + if err != nil { + log.Fatalln("bad internal ABI constant", err) + } + InternalQGBabi = internalABI + + solValidatorType, err := abi.NewType("tuple", "validator", []abi.ArgumentMarshaling{ + {Name: "Addr", Type: "address"}, + {Name: "Power", Type: "uint256"}, + }) + if err != nil { + panic(err) + } + + BridgeValidatorAbi = abi.Arguments{ + {Type: solValidatorType, Name: "Validator"}, + } + + // create the domain separator for valset hashes + VsDomainSeparator = ethcmn.HexToHash(ValidatorSetDomainSeparator) + DcDomainSeparator = ethcmn.HexToHash(DataCommitmentDomainSeparator) +} diff --git a/x/qgb/types/attestation.go b/x/qgb/types/attestation.go new file mode 100644 index 0000000000..e9d2167fc1 --- /dev/null +++ b/x/qgb/types/attestation.go @@ -0,0 +1,23 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/gogo/protobuf/proto" +) + +type AttestationType int64 + +const ( + DataCommitmentRequestType AttestationType = iota + ValsetRequestType +) + +// AttestationRequestI is either a DataCommitment or a Valset. +// This was decided as part of the universal nonce approach under: +// https://github.com/celestiaorg/celestia-app/issues/468#issuecomment-1156887715 +type AttestationRequestI interface { + proto.Message + codec.ProtoMarshaler + Type() AttestationType + GetNonce() uint64 +} diff --git a/x/qgb/types/codec.go b/x/qgb/types/codec.go index 57636d9962..bdd431a0d8 100644 --- a/x/qgb/types/codec.go +++ b/x/qgb/types/codec.go @@ -2,24 +2,28 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/types/msgservice" - cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" ) func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgDataCommitmentConfirm{}, "qgb/DataCommitmentConfirm", nil) - cdc.RegisterConcrete(&MsgValsetConfirm{}, "qgb/ValSetConfirm", nil) + cdc.RegisterConcrete(&MsgValsetConfirm{}, "qgb/MsgValSetConfirm", nil) } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { - registry.RegisterImplementations((*sdk.Msg)(nil), + registry.RegisterImplementations( + (*sdk.Msg)(nil), &MsgDataCommitmentConfirm{}, + &MsgValsetConfirm{}, ) - registry.RegisterImplementations((*sdk.Msg)(nil), - &MsgValsetConfirm{}, + registry.RegisterInterface( + "AttestationRequestI", + (*AttestationRequestI)(nil), + &DataCommitment{}, + &Valset{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/qgb/types/data_commitment.go b/x/qgb/types/data_commitment.go new file mode 100644 index 0000000000..f67b220199 --- /dev/null +++ b/x/qgb/types/data_commitment.go @@ -0,0 +1,20 @@ +package types + +var _ AttestationRequestI = &DataCommitment{} + +// NewDataCommitment creates a new DataCommitment. +func NewDataCommitment( + nonce uint64, + beginBlock uint64, + endBlock uint64, +) *DataCommitment { + return &DataCommitment{ + Nonce: nonce, + BeginBlock: beginBlock, + EndBlock: endBlock, + } +} + +func (m *DataCommitment) Type() AttestationType { + return DataCommitmentRequestType +} diff --git a/x/qgb/types/data_commitment_confirm.go b/x/qgb/types/data_commitment_confirm.go new file mode 100644 index 0000000000..304ea62f73 --- /dev/null +++ b/x/qgb/types/data_commitment_confirm.go @@ -0,0 +1,35 @@ +package types + +import ( + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + ethcmn "github.com/ethereum/go-ethereum/common" +) + +// GetSigners defines whose signature is required. +func (msg *MsgDataCommitmentConfirm) GetSigners() []sdk.AccAddress { + acc, err := sdk.AccAddressFromBech32(msg.ValidatorAddress) + if err != nil { + panic(err) + } + return []sdk.AccAddress{acc} +} + +// ValidateBasic performs stateless checks. +func (msg *MsgDataCommitmentConfirm) ValidateBasic() (err error) { + if _, err = sdk.AccAddressFromBech32(msg.ValidatorAddress); err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.ValidatorAddress) + } + if msg.BeginBlock > msg.EndBlock { + return sdkerrors.Wrap(ErrInvalid, "begin block should be less than end block") + } + if !ethcmn.IsHexAddress(msg.EthAddress) { + return sdkerrors.Wrap(stakingtypes.ErrEthAddressNotHex, "ethereum address") + } + return nil +} + +// Type should return the action. +func (msg *MsgDataCommitmentConfirm) Type() string { return "data_commitment_confirm" } diff --git a/x/qgb/types/datacommitmentconfirm.go b/x/qgb/types/datacommitmentconfirm.go deleted file mode 100644 index 2fcb17a476..0000000000 --- a/x/qgb/types/datacommitmentconfirm.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -import sdk "github.com/cosmos/cosmos-sdk/types" - -// GetSigners defines whose signature is required -func (msg *MsgDataCommitmentConfirm) GetSigners() []sdk.AccAddress { - // TODO - return []sdk.AccAddress{} -} - -// ValidateBasic -func (msg *MsgDataCommitmentConfirm) ValidateBasic() error { - // TODO - return nil -} diff --git a/x/qgb/types/errors.go b/x/qgb/types/errors.go new file mode 100644 index 0000000000..2f29236ecb --- /dev/null +++ b/x/qgb/types/errors.go @@ -0,0 +1,27 @@ +package types + +import sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + +var ( + ErrInvalid = sdkerrors.Register(ModuleName, 3, "invalid") + ErrDuplicate = sdkerrors.Register(ModuleName, 2, "duplicate") + ErrUnknown = sdkerrors.Register(ModuleName, 5, "unknown") + ErrEmpty = sdkerrors.Register(ModuleName, 6, "empty") + ErrResetDelegateKeys = sdkerrors.Register(ModuleName, 10, "can not set orchestrator addresses more than once") + ErrNoValidators = sdkerrors.Register(ModuleName, 12, "no bonded validators in active set") + ErrInvalidValAddress = sdkerrors.Register(ModuleName, 13, "invalid validator address in current valset %v") + ErrInvalidEthAddress = sdkerrors.Register(ModuleName, 14, "discovered invalid eth address stored for validator %v") + ErrInvalidValset = sdkerrors.Register(ModuleName, 15, "generated invalid valset") + ErrAttestationNotValsetRequest = sdkerrors.Register(ModuleName, 16, "attestation is not a valset request") + ErrAttestationNotDataCommitmentRequest = sdkerrors.Register(ModuleName, 17, "attestation is not a data commitment request") + ErrAttestationNotFound = sdkerrors.Register(ModuleName, 18, "attestation not found") + ErrNilDataCommitmentRequest = sdkerrors.Register(ModuleName, 19, "data commitment cannot be nil when setting attestation") //nolint:lll + ErrNilValsetRequest = sdkerrors.Register(ModuleName, 20, "valset cannot be nil when setting attestation") + ErrValidatorNotInValset = sdkerrors.Register(ModuleName, 21, "validator signing is not in the valset") + ErrNilAttestation = sdkerrors.Register(ModuleName, 22, "nil attestation") + ErrAttestationNotCastToDataCommitment = sdkerrors.Register(ModuleName, 23, "couldn't cast attestation to data commitment") + ErrWindowNotFound = sdkerrors.Register(ModuleName, 25, "couldn't find data commitment window in store") + ErrUnmarshalllAttestation = sdkerrors.Register(ModuleName, 26, "couldn't unmarshall attestation from store") + ErrNonceHigherThanLatestAttestationNonce = sdkerrors.Register(ModuleName, 27, "the provided nonce is higher than the latest attestation nonce") + ErrNoValsetBeforeNonceOne = sdkerrors.Register(ModuleName, 28, "there is no valset before attestation nonce 1") +) diff --git a/x/qgb/types/events.go b/x/qgb/types/events.go new file mode 100644 index 0000000000..80b4f9c9e5 --- /dev/null +++ b/x/qgb/types/events.go @@ -0,0 +1,6 @@ +package types + +const ( + EventTypeAttestationRequest = "AttestationRequest" + AttributeKeyNonce = "nonce" +) diff --git a/x/qgb/types/genesis.go b/x/qgb/types/genesis.go index 094d1119cc..3019321bee 100644 --- a/x/qgb/types/genesis.go +++ b/x/qgb/types/genesis.go @@ -1,15 +1,67 @@ package types -// DefaultIndex is the default capability global index -const DefaultIndex uint64 = 1 +import ( + "fmt" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" +) + +// DefaultParamspace defines the default qgb module parameter subspace +const ( + DefaultParamspace = ModuleName +) + +// ParamsStoreKeyDataCommitmentWindow +var ParamsStoreKeyDataCommitmentWindow = []byte("DataCommitmentWindow") // DefaultGenesis returns the default Capability genesis state func DefaultGenesis() *GenesisState { - return &GenesisState{} + return &GenesisState{ + Params: &Params{ + DataCommitmentWindow: 400, + }, + } } // Validate performs basic genesis state validation returning an error upon any // failure. func (gs GenesisState) Validate() error { + // this line is used by starport scaffolding # genesis/types/validate + if err := gs.Params.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "params") + } + return nil +} + +// ParamKeyTable for qgb module +func ParamKeyTable() paramtypes.KeyTable { + return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) +} + +// ParamSetPairs implements the ParamSet interface and returns all the key/value +// pairs of auth module's parameters. +func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { + return paramtypes.ParamSetPairs{ + paramtypes.NewParamSetPair(ParamsStoreKeyDataCommitmentWindow, &p.DataCommitmentWindow, validateDataCommitmentWindow), + } +} + +func validateDataCommitmentWindow(i interface{}) error { + val, ok := i.(uint64) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } else if val < 100 { + return fmt.Errorf("invalid average Ethereum block time, too short for latency limitations") + } + return nil +} + +// ValidateBasic checks that the parameters have valid values. +func (p Params) ValidateBasic() error { + if err := validateDataCommitmentWindow(p.DataCommitmentWindow); err != nil { + return sdkerrors.Wrap(err, "data commitment window") + } return nil } diff --git a/x/qgb/types/genesis.pb.go b/x/qgb/types/genesis.pb.go index 5d24ce1db9..3233365ac5 100644 --- a/x/qgb/types/genesis.pb.go +++ b/x/qgb/types/genesis.pb.go @@ -5,6 +5,7 @@ package types import ( fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" io "io" math "math" @@ -22,15 +23,62 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// GenesisState defines the capability module's genesis state. +// Params represent the Quantum Gravity Bridge genesis and store parameters. +type Params struct { + DataCommitmentWindow uint64 `protobuf:"varint,1,opt,name=data_commitment_window,json=dataCommitmentWindow,proto3" json:"data_commitment_window,omitempty"` +} + +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_afeb526ae8d4446d, []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 (m *Params) GetDataCommitmentWindow() uint64 { + if m != nil { + return m.DataCommitmentWindow + } + return 0 +} + +// GenesisState struct, containing all persistant data required by the Gravity +// module type GenesisState struct { + Params *Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` } func (m *GenesisState) Reset() { *m = GenesisState{} } func (m *GenesisState) String() string { return proto.CompactTextString(m) } func (*GenesisState) ProtoMessage() {} func (*GenesisState) Descriptor() ([]byte, []int) { - return fileDescriptor_afeb526ae8d4446d, []int{0} + return fileDescriptor_afeb526ae8d4446d, []int{1} } func (m *GenesisState) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -59,23 +107,65 @@ func (m *GenesisState) XXX_DiscardUnknown() { var xxx_messageInfo_GenesisState proto.InternalMessageInfo +func (m *GenesisState) GetParams() *Params { + if m != nil { + return m.Params + } + return nil +} + func init() { + proto.RegisterType((*Params)(nil), "qgb.Params") proto.RegisterType((*GenesisState)(nil), "qgb.GenesisState") } func init() { proto.RegisterFile("qgb/genesis.proto", fileDescriptor_afeb526ae8d4446d) } var fileDescriptor_afeb526ae8d4446d = []byte{ - // 132 bytes of a gzipped FileDescriptorProto + // 239 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2c, 0x4c, 0x4f, 0xd2, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2e, - 0x4c, 0x4f, 0x52, 0xe2, 0xe3, 0xe2, 0x71, 0x87, 0x88, 0x06, 0x97, 0x24, 0x96, 0xa4, 0x3a, 0x79, - 0x9e, 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, 0x7e, 0x7a, 0x66, 0x49, 0x46, - 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x72, 0x6a, 0x4e, 0x6a, 0x71, 0x49, 0x66, 0x62, 0x7e, - 0x51, 0x3a, 0x9c, 0xad, 0x9b, 0x58, 0x50, 0xa0, 0x5f, 0xa1, 0x0f, 0xb2, 0xa7, 0xa4, 0xb2, 0x20, - 0xb5, 0x38, 0x89, 0x0d, 0x6c, 0x8d, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x88, 0xcb, 0xb9, 0x1a, - 0x7b, 0x00, 0x00, 0x00, + 0x4c, 0x4f, 0x92, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xf3, 0xf5, 0x41, 0x2c, 0x88, 0x94, 0x14, + 0x3f, 0x48, 0x75, 0x49, 0x65, 0x41, 0x2a, 0x54, 0xad, 0x14, 0x1f, 0x48, 0x20, 0xb7, 0x38, 0x1d, + 0xca, 0x57, 0x72, 0xe1, 0x62, 0x0b, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0x16, 0x32, 0xe1, 0x12, 0x4b, + 0x49, 0x2c, 0x49, 0x8c, 0x4f, 0xce, 0xcf, 0xcd, 0xcd, 0x2c, 0xc9, 0x4d, 0xcd, 0x2b, 0x89, 0x2f, + 0xcf, 0xcc, 0x4b, 0xc9, 0x2f, 0x97, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x09, 0x12, 0x01, 0xc9, 0x3a, + 0xc3, 0x25, 0xc3, 0xc1, 0x72, 0x56, 0x2c, 0x0d, 0x77, 0x14, 0x18, 0x94, 0x8c, 0xb9, 0x78, 0xdc, + 0x21, 0x4e, 0x0a, 0x2e, 0x49, 0x2c, 0x49, 0x15, 0x52, 0xe6, 0x62, 0x2b, 0x00, 0x9b, 0x0a, 0xd6, + 0xcb, 0x6d, 0xc4, 0xad, 0x57, 0x98, 0x9e, 0xa4, 0x07, 0xb1, 0x28, 0x08, 0x2a, 0xe5, 0xe4, 0x79, + 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, 0xfa, 0xe9, 0x99, 0x25, 0x19, 0xa5, + 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xc9, 0xa9, 0x39, 0xa9, 0xc5, 0x25, 0x99, 0x89, 0xf9, 0x45, + 0xe9, 0x70, 0xb6, 0x6e, 0x62, 0x41, 0x81, 0x7e, 0x85, 0x3e, 0xdc, 0x6f, 0x49, 0x6c, 0x60, 0xcf, + 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xec, 0xaf, 0x19, 0x47, 0x1d, 0x01, 0x00, 0x00, +} + +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 + if m.DataCommitmentWindow != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.DataCommitmentWindow)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -98,6 +188,18 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Params != nil { + { + 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 } @@ -112,12 +214,28 @@ func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DataCommitmentWindow != 0 { + n += 1 + sovGenesis(uint64(m.DataCommitmentWindow)) + } + return n +} + func (m *GenesisState) Size() (n int) { if m == nil { return 0 } var l int _ = l + if m.Params != nil { + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + } return n } @@ -127,6 +245,75 @@ func sovGenesis(x uint64) (n int) { func sozGenesis(x uint64) (n int) { return sovGenesis(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 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: 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 { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DataCommitmentWindow", wireType) + } + m.DataCommitmentWindow = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DataCommitmentWindow |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 (m *GenesisState) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -156,6 +343,42 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { 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 m.Params == nil { + m.Params = &Params{} + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/qgb/types/genesis_test.go b/x/qgb/types/genesis_test.go new file mode 100644 index 0000000000..a187a62161 --- /dev/null +++ b/x/qgb/types/genesis_test.go @@ -0,0 +1,36 @@ +package types_test + +import ( + "testing" + + "github.com/celestiaorg/celestia-app/x/qgb/types" + + "github.com/stretchr/testify/require" +) + +func TestGenesisStateValidate(t *testing.T) { + specs := map[string]struct { + src *types.GenesisState + expErr bool + }{ + "default params": {src: types.DefaultGenesis(), expErr: false}, + "empty params": {src: &types.GenesisState{ + Params: &types.Params{}, + }, expErr: true}, + "invalid params: short block time": {src: &types.GenesisState{ + Params: &types.Params{ + DataCommitmentWindow: 10, + }, + }, expErr: true}, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.Validate() + if spec.expErr { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} diff --git a/x/qgb/types/keys.go b/x/qgb/types/keys.go index 2220caae92..d6397778c4 100644 --- a/x/qgb/types/keys.go +++ b/x/qgb/types/keys.go @@ -1,18 +1,48 @@ package types +import ( + "strings" +) + const ( - // ModuleName is the name of the module - ModuleName = "gqb" + // ModuleName is the name of the module. + ModuleName = "qgb" - // StoreKey to be used when creating the KVStore + // StoreKey to be used when creating the KVStore. StoreKey = ModuleName - // RouterKey is the module name router key + // RouterKey is the module name router key. RouterKey = ModuleName - // QuerierRoute to be used for querierer msgs + // QuerierRoute to be used for querier msgs. QuerierRoute = ModuleName - // MemStoreKey defines the in-memory store key - MemStoreKey = "mem_payment" + // MemStoreKey defines the in-memory store key. + MemStoreKey = "mem_qgb" ) + +const ( + // AttestationRequestKey indexes attestation requests by nonce + AttestationRequestKey = "AttestationRequestKey" + + // LastUnBondingBlockHeight indexes the last validator unbonding block height + LastUnBondingBlockHeight = "LastUnBondingBlockHeight" + + // LatestAttestationtNonce indexes the latest attestation request nonce + LatestAttestationtNonce = "LatestAttestationNonce" +) + +// GetAttestationKey returns the following key format +// prefix nonce +// [0x0][0 0 0 0 0 0 0 1] +func GetAttestationKey(nonce uint64) string { + return AttestationRequestKey + string(UInt64Bytes(nonce)) +} + +func ConvertByteArrToString(value []byte) string { + var ret strings.Builder + for i := 0; i < len(value); i++ { + ret.WriteString(string(value[i])) + } + return ret.String() +} diff --git a/x/qgb/types/msgs.pb.go b/x/qgb/types/msgs.pb.go index 49dbd62241..6063a1e074 100644 --- a/x/qgb/types/msgs.pb.go +++ b/x/qgb/types/msgs.pb.go @@ -45,10 +45,15 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // chain store and submit them to Ethereum to update the validator set // ------------- type MsgValsetConfirm struct { - Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` + // Universal nonce referencing the `ValSet`. + Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` + // Orchestrator `celes1` account address. Orchestrator string `protobuf:"bytes,2,opt,name=orchestrator,proto3" json:"orchestrator,omitempty"` - EthAddress string `protobuf:"bytes,3,opt,name=eth_address,json=ethAddress,proto3" json:"eth_address,omitempty"` - Signature string `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"` + // Ethereum address, associated to the orchestrator, used to sign the `ValSet` + // message. + EthAddress string `protobuf:"bytes,3,opt,name=eth_address,json=ethAddress,proto3" json:"eth_address,omitempty"` + // The `ValSet` message signature. + Signature string `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"` } func (m *MsgValsetConfirm) Reset() { *m = MsgValsetConfirm{} } @@ -152,6 +157,25 @@ var xxx_messageInfo_MsgValsetConfirmResponse proto.InternalMessageInfo // MsgDataCommitmentConfirm describes a data commitment for a set of blocks. type MsgDataCommitmentConfirm struct { + // Universal nonce referencing the Data Commitment. + Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` + // Signature over the commitment, the range of blocks, the validator address + // and the Ethereum address. + Signature string `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + // Orchestrator account address who will be signing the message. + ValidatorAddress string `protobuf:"bytes,3,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` + // Hex `0x` encoded Ethereum public key that will be used by this validator on + // Ethereum. + EthAddress string `protobuf:"bytes,4,opt,name=eth_address,json=ethAddress,proto3" json:"eth_address,omitempty"` + // Merkle root over a merkle tree containing the data roots of a set of + // blocks. + Commitment string `protobuf:"bytes,5,opt,name=commitment,proto3" json:"commitment,omitempty"` + // First block defining the ordered set of blocks used to create the + // commitment. + BeginBlock uint64 `protobuf:"varint,6,opt,name=begin_block,json=beginBlock,proto3" json:"begin_block,omitempty"` + // Last block defining the ordered set of blocks used to create the + // commitment. + EndBlock uint64 `protobuf:"varint,7,opt,name=end_block,json=endBlock,proto3" json:"end_block,omitempty"` } func (m *MsgDataCommitmentConfirm) Reset() { *m = MsgDataCommitmentConfirm{} } @@ -187,6 +211,55 @@ func (m *MsgDataCommitmentConfirm) XXX_DiscardUnknown() { var xxx_messageInfo_MsgDataCommitmentConfirm proto.InternalMessageInfo +func (m *MsgDataCommitmentConfirm) GetNonce() uint64 { + if m != nil { + return m.Nonce + } + return 0 +} + +func (m *MsgDataCommitmentConfirm) GetSignature() string { + if m != nil { + return m.Signature + } + return "" +} + +func (m *MsgDataCommitmentConfirm) GetValidatorAddress() string { + if m != nil { + return m.ValidatorAddress + } + return "" +} + +func (m *MsgDataCommitmentConfirm) GetEthAddress() string { + if m != nil { + return m.EthAddress + } + return "" +} + +func (m *MsgDataCommitmentConfirm) GetCommitment() string { + if m != nil { + return m.Commitment + } + return "" +} + +func (m *MsgDataCommitmentConfirm) GetBeginBlock() uint64 { + if m != nil { + return m.BeginBlock + } + return 0 +} + +func (m *MsgDataCommitmentConfirm) GetEndBlock() uint64 { + if m != nil { + return m.EndBlock + } + return 0 +} + // MsgValsetConfirmResponse describes the response returned after the submission // of a MsgDataCommitmentConfirm. type MsgDataCommitmentConfirmResponse struct { @@ -235,31 +308,36 @@ func init() { func init() { proto.RegisterFile("qgb/msgs.proto", fileDescriptor_c696c358dc748aba) } var fileDescriptor_c696c358dc748aba = []byte{ - // 374 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0x3d, 0x4f, 0xe3, 0x40, - 0x14, 0xcc, 0x26, 0xb9, 0x93, 0xb2, 0xf7, 0xa1, 0x93, 0x2f, 0x91, 0x2c, 0x5f, 0xce, 0x17, 0x59, - 0x77, 0x52, 0x9a, 0xf3, 0x4a, 0xf0, 0x0b, 0x20, 0x34, 0x14, 0x69, 0x52, 0x50, 0xd0, 0x44, 0x6b, - 0x67, 0x59, 0x5b, 0x8a, 0xf7, 0x39, 0xbb, 0x2f, 0x08, 0x5a, 0x28, 0x69, 0x90, 0xf8, 0x53, 0x94, - 0x91, 0x68, 0x28, 0x51, 0x42, 0xcf, 0x5f, 0x40, 0xd9, 0xc4, 0x46, 0x89, 0x02, 0xdd, 0x7b, 0x33, - 0xf3, 0x66, 0xc6, 0xf2, 0xd2, 0xef, 0x13, 0x19, 0xb1, 0xcc, 0x48, 0x13, 0xe6, 0x1a, 0x10, 0x9c, - 0xda, 0x44, 0x46, 0x5e, 0x53, 0x82, 0x04, 0xbb, 0xb3, 0xe5, 0xb4, 0xa2, 0xbc, 0xb6, 0x04, 0x90, - 0x63, 0xc1, 0x78, 0x9e, 0x32, 0xae, 0x14, 0x20, 0xc7, 0x14, 0xd4, 0xfa, 0x30, 0xb8, 0x21, 0xf4, - 0x47, 0xdf, 0xc8, 0x13, 0x3e, 0x36, 0x02, 0x7b, 0xa0, 0xce, 0x52, 0x9d, 0x39, 0x4d, 0xfa, 0x49, - 0x81, 0x8a, 0x85, 0x4b, 0x3a, 0xa4, 0x5b, 0x1f, 0xac, 0x16, 0x27, 0xa0, 0x5f, 0x41, 0xc7, 0x89, - 0x30, 0xa8, 0x39, 0x82, 0x76, 0xab, 0x1d, 0xd2, 0x6d, 0x0c, 0x36, 0x30, 0xe7, 0x0f, 0xfd, 0x22, - 0x30, 0x19, 0xf2, 0xd1, 0x48, 0x0b, 0x63, 0xdc, 0x9a, 0x95, 0x50, 0x81, 0xc9, 0xc1, 0x0a, 0x71, - 0xda, 0xb4, 0x61, 0x52, 0xa9, 0x38, 0x4e, 0xb5, 0x70, 0xeb, 0x96, 0x7e, 0x03, 0x02, 0x8f, 0xba, - 0xdb, 0x65, 0x06, 0xc2, 0xe4, 0xa0, 0x4c, 0xc1, 0x1d, 0x71, 0xe4, 0x3d, 0xc8, 0xb2, 0x14, 0x33, - 0xa1, 0x0a, 0x4d, 0x10, 0xd0, 0xce, 0x7b, 0x5c, 0x71, 0xbf, 0xf7, 0x42, 0x68, 0xad, 0x6f, 0xa4, - 0x13, 0xd1, 0x6f, 0x9b, 0x5f, 0xdb, 0x0a, 0x27, 0x32, 0x0a, 0xb7, 0x73, 0xbd, 0xdf, 0x3b, 0xe1, - 0xb2, 0xce, 0xaf, 0xab, 0x87, 0xe7, 0xbb, 0x6a, 0x2b, 0xf8, 0xc9, 0x96, 0xbf, 0xe2, 0xdc, 0x6a, - 0x86, 0xf1, 0xda, 0xf2, 0x9a, 0xd0, 0xd6, 0xce, 0x36, 0x4e, 0xe9, 0xba, 0x93, 0xf6, 0xfe, 0x7d, - 0x48, 0x97, 0xe1, 0x7f, 0x6d, 0xb8, 0x1f, 0xb4, 0x6d, 0xf8, 0x88, 0x23, 0x1f, 0xc6, 0xa5, 0xb8, - 0x68, 0x71, 0x78, 0x7c, 0x3f, 0xf7, 0xc9, 0x6c, 0xee, 0x93, 0xa7, 0xb9, 0x4f, 0x6e, 0x17, 0x7e, - 0x65, 0xb6, 0xf0, 0x2b, 0x8f, 0x0b, 0xbf, 0x72, 0xca, 0x64, 0x8a, 0xc9, 0x34, 0x0a, 0x63, 0xc8, - 0x58, 0x2c, 0xc6, 0xc2, 0x60, 0xca, 0x41, 0xcb, 0x72, 0xfe, 0xcf, 0xf3, 0x9c, 0x5d, 0x58, 0x73, - 0xbc, 0xcc, 0x85, 0x89, 0x3e, 0xdb, 0xd7, 0xb2, 0xff, 0x1a, 0x00, 0x00, 0xff, 0xff, 0x07, 0xdd, - 0x60, 0xa7, 0x78, 0x02, 0x00, 0x00, + // 450 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xbf, 0x8f, 0xd3, 0x30, + 0x14, 0xc7, 0xeb, 0xb6, 0x77, 0xd0, 0xc7, 0x0f, 0x1d, 0xe1, 0x2a, 0x45, 0xb9, 0x12, 0xaa, 0x08, + 0xa4, 0x93, 0x10, 0x8d, 0x04, 0x7f, 0x01, 0x77, 0x2c, 0x0c, 0xb7, 0x74, 0x60, 0x60, 0xa9, 0x9c, + 0xe4, 0xe1, 0x5a, 0x24, 0x7e, 0xa9, 0xed, 0x3b, 0xc1, 0x0a, 0x23, 0x0b, 0x12, 0xff, 0x14, 0x63, + 0x25, 0x16, 0x46, 0xd4, 0xb2, 0xb3, 0x33, 0xa1, 0xb8, 0x6d, 0xaa, 0x86, 0x02, 0x9b, 0xfd, 0xfd, + 0x38, 0xef, 0xfb, 0x7d, 0xcf, 0x31, 0xdc, 0x9e, 0x89, 0x24, 0x2e, 0x8c, 0x30, 0xa3, 0x52, 0x93, + 0x25, 0xaf, 0x33, 0x13, 0x49, 0x70, 0x2c, 0x48, 0x90, 0xdb, 0xc7, 0xd5, 0x6a, 0x85, 0x82, 0x81, + 0x20, 0x12, 0x39, 0xc6, 0xbc, 0x94, 0x31, 0x57, 0x8a, 0x2c, 0xb7, 0x92, 0xd4, 0xfa, 0xc3, 0xe8, + 0x23, 0x83, 0xa3, 0x0b, 0x23, 0x5e, 0xf2, 0xdc, 0xa0, 0x3d, 0x27, 0xf5, 0x5a, 0xea, 0xc2, 0x3b, + 0x86, 0x03, 0x45, 0x2a, 0x45, 0x9f, 0x0d, 0xd9, 0x69, 0x77, 0xbc, 0xda, 0x78, 0x11, 0xdc, 0x24, + 0x9d, 0x4e, 0xd1, 0x58, 0xcd, 0x2d, 0x69, 0xbf, 0x3d, 0x64, 0xa7, 0xbd, 0xf1, 0x8e, 0xe6, 0xdd, + 0x87, 0x1b, 0x68, 0xa7, 0x13, 0x9e, 0x65, 0x1a, 0x8d, 0xf1, 0x3b, 0xee, 0x08, 0xa0, 0x9d, 0x3e, + 0x5b, 0x29, 0xde, 0x00, 0x7a, 0x46, 0x0a, 0xc5, 0xed, 0xa5, 0x46, 0xbf, 0xeb, 0xf0, 0x56, 0x88, + 0x02, 0xf0, 0x9b, 0x61, 0xc6, 0x68, 0x4a, 0x52, 0x06, 0xa3, 0x5f, 0xcc, 0xc1, 0xe7, 0xdc, 0xf2, + 0x73, 0x2a, 0x0a, 0x69, 0x0b, 0x54, 0xff, 0x49, 0xbc, 0x63, 0xd6, 0x6e, 0x98, 0x79, 0x8f, 0xe0, + 0xce, 0x15, 0xcf, 0x65, 0x56, 0x05, 0x6f, 0x24, 0x3e, 0xaa, 0xc1, 0x26, 0x77, 0xa3, 0xb1, 0xee, + 0x1f, 0x8d, 0x85, 0x00, 0x69, 0x1d, 0xcb, 0x3f, 0x58, 0xf1, 0xad, 0x52, 0x15, 0x48, 0x50, 0x48, + 0x35, 0x49, 0x72, 0x4a, 0xdf, 0xf8, 0x87, 0x2e, 0x27, 0x38, 0xe9, 0xac, 0x52, 0xbc, 0x13, 0xe8, + 0xa1, 0xca, 0xd6, 0xf8, 0x9a, 0xc3, 0xd7, 0x51, 0x65, 0x0e, 0x46, 0x11, 0x0c, 0xff, 0xd6, 0xfb, + 0x66, 0x40, 0x4f, 0x7e, 0x32, 0xe8, 0x5c, 0x18, 0xe1, 0x25, 0x70, 0x6b, 0xf7, 0x3a, 0xfb, 0xa3, + 0x99, 0x48, 0x46, 0xcd, 0xc1, 0x06, 0xf7, 0xf6, 0xca, 0xf5, 0xbc, 0x4f, 0xde, 0x7f, 0xfd, 0xf1, + 0xb9, 0xdd, 0x8f, 0xee, 0xc6, 0xd5, 0xbf, 0x76, 0xe5, 0xce, 0x4c, 0xd2, 0x75, 0xc9, 0x0f, 0x0c, + 0xfa, 0xfb, 0x6f, 0xa2, 0xae, 0xba, 0x17, 0x07, 0x0f, 0xff, 0x89, 0x6b, 0xf3, 0x07, 0xce, 0x3c, + 0x8c, 0x06, 0xce, 0x3c, 0xe3, 0x96, 0x4f, 0xb6, 0xb3, 0xdc, 0xa4, 0x38, 0x7b, 0xf1, 0x65, 0x11, + 0xb2, 0xf9, 0x22, 0x64, 0xdf, 0x17, 0x21, 0xfb, 0xb4, 0x0c, 0x5b, 0xf3, 0x65, 0xd8, 0xfa, 0xb6, + 0x0c, 0x5b, 0xaf, 0x62, 0x21, 0xed, 0xf4, 0x32, 0x19, 0xa5, 0x54, 0xc4, 0x29, 0xe6, 0x68, 0xac, + 0xe4, 0xa4, 0x45, 0xbd, 0x7e, 0xcc, 0xcb, 0x32, 0x7e, 0xeb, 0x8a, 0xdb, 0x77, 0x25, 0x9a, 0xe4, + 0xd0, 0x3d, 0x87, 0xa7, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe6, 0xb0, 0xbd, 0xe7, 0x59, 0x03, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -274,9 +352,11 @@ const _ = grpc.SupportPackageIsVersion4 // // 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 { - // ValsetConfirm allows the validators to submit their signatures over the validator set. + // ValsetConfirm allows the validators to submit their signatures over the + // validator set. ValsetConfirm(ctx context.Context, in *MsgValsetConfirm, opts ...grpc.CallOption) (*MsgValsetConfirmResponse, error) - // DataCommitmentConfirm allows the validators to submit a confirmation for a data commitment. + // DataCommitmentConfirm allows the validators to submit a confirmation for a + // data commitment. DataCommitmentConfirm(ctx context.Context, in *MsgDataCommitmentConfirm, opts ...grpc.CallOption) (*MsgDataCommitmentConfirmResponse, error) } @@ -308,9 +388,11 @@ func (c *msgClient) DataCommitmentConfirm(ctx context.Context, in *MsgDataCommit // MsgServer is the server API for Msg service. type MsgServer interface { - // ValsetConfirm allows the validators to submit their signatures over the validator set. + // ValsetConfirm allows the validators to submit their signatures over the + // validator set. ValsetConfirm(context.Context, *MsgValsetConfirm) (*MsgValsetConfirmResponse, error) - // DataCommitmentConfirm allows the validators to submit a confirmation for a data commitment. + // DataCommitmentConfirm allows the validators to submit a confirmation for a + // data commitment. DataCommitmentConfirm(context.Context, *MsgDataCommitmentConfirm) (*MsgDataCommitmentConfirmResponse, error) } @@ -474,6 +556,49 @@ func (m *MsgDataCommitmentConfirm) MarshalToSizedBuffer(dAtA []byte) (int, error _ = i var l int _ = l + if m.EndBlock != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.EndBlock)) + i-- + dAtA[i] = 0x38 + } + if m.BeginBlock != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.BeginBlock)) + i-- + dAtA[i] = 0x30 + } + if len(m.Commitment) > 0 { + i -= len(m.Commitment) + copy(dAtA[i:], m.Commitment) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Commitment))) + i-- + dAtA[i] = 0x2a + } + if len(m.EthAddress) > 0 { + i -= len(m.EthAddress) + copy(dAtA[i:], m.EthAddress) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.EthAddress))) + i-- + dAtA[i] = 0x22 + } + if len(m.ValidatorAddress) > 0 { + i -= len(m.ValidatorAddress) + copy(dAtA[i:], m.ValidatorAddress) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.ValidatorAddress))) + i-- + dAtA[i] = 0x1a + } + if len(m.Signature) > 0 { + i -= len(m.Signature) + copy(dAtA[i:], m.Signature) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Signature))) + i-- + dAtA[i] = 0x12 + } + if m.Nonce != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.Nonce)) + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } @@ -550,6 +675,31 @@ func (m *MsgDataCommitmentConfirm) Size() (n int) { } var l int _ = l + if m.Nonce != 0 { + n += 1 + sovMsgs(uint64(m.Nonce)) + } + l = len(m.Signature) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.EthAddress) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Commitment) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + if m.BeginBlock != 0 { + n += 1 + sovMsgs(uint64(m.BeginBlock)) + } + if m.EndBlock != 0 { + n += 1 + sovMsgs(uint64(m.EndBlock)) + } return n } @@ -812,6 +962,191 @@ func (m *MsgDataCommitmentConfirm) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: MsgDataCommitmentConfirm: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType) + } + m.Nonce = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Nonce |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + 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 ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signature = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + 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 ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EthAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + 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 ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.EthAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commitment", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + 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 ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Commitment = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + m.BeginBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BeginBlock |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + m.EndBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.EndBlock |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipMsgs(dAtA[iNdEx:]) diff --git a/x/qgb/types/msgs.pb.gw.go b/x/qgb/types/msgs.pb.gw.go index 627dd386c6..33b7ad3cae 100644 --- a/x/qgb/types/msgs.pb.gw.go +++ b/x/qgb/types/msgs.pb.gw.go @@ -69,10 +69,21 @@ func local_request_Msg_ValsetConfirm_0(ctx context.Context, marshaler runtime.Ma } +var ( + filter_Msg_DataCommitmentConfirm_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + func request_Msg_DataCommitmentConfirm_0(ctx context.Context, marshaler runtime.Marshaler, client MsgClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq MsgDataCommitmentConfirm var metadata runtime.ServerMetadata + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Msg_DataCommitmentConfirm_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.DataCommitmentConfirm(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -82,6 +93,13 @@ func local_request_Msg_DataCommitmentConfirm_0(ctx context.Context, marshaler ru var protoReq MsgDataCommitmentConfirm var metadata runtime.ServerMetadata + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Msg_DataCommitmentConfirm_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.DataCommitmentConfirm(ctx, &protoReq) return msg, metadata, err diff --git a/x/qgb/types/query.pb.go b/x/qgb/types/query.pb.go index 8fb42b0585..3a76a73053 100644 --- a/x/qgb/types/query.pb.go +++ b/x/qgb/types/query.pb.go @@ -6,12 +6,19 @@ package types import ( context "context" fmt "fmt" + types "github.com/cosmos/cosmos-sdk/codec/types" _ "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" grpc1 "github.com/gogo/protobuf/grpc" proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-proto" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. @@ -25,22 +32,500 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// QueryParamsRequest +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_f3c1fd86445aad81, []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 +type QueryParamsResponse struct { + 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_f3c1fd86445aad81, []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{} +} + +// QueryAttestationRequestByNonceRequest +type QueryAttestationRequestByNonceRequest struct { + Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` +} + +func (m *QueryAttestationRequestByNonceRequest) Reset() { *m = QueryAttestationRequestByNonceRequest{} } +func (m *QueryAttestationRequestByNonceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAttestationRequestByNonceRequest) ProtoMessage() {} +func (*QueryAttestationRequestByNonceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f3c1fd86445aad81, []int{2} +} +func (m *QueryAttestationRequestByNonceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAttestationRequestByNonceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAttestationRequestByNonceRequest.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 *QueryAttestationRequestByNonceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAttestationRequestByNonceRequest.Merge(m, src) +} +func (m *QueryAttestationRequestByNonceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAttestationRequestByNonceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAttestationRequestByNonceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAttestationRequestByNonceRequest proto.InternalMessageInfo + +func (m *QueryAttestationRequestByNonceRequest) GetNonce() uint64 { + if m != nil { + return m.Nonce + } + return 0 +} + +// QueryAttestationRequestByNonceResponse +type QueryAttestationRequestByNonceResponse struct { + // AttestationRequestI is either a Data Commitment or a Valset. + // This was decided as part of the universal nonce approach under: + // https://github.com/celestiaorg/celestia-app/issues/468#issuecomment-1156887715 + Attestation *types.Any `protobuf:"bytes,1,opt,name=attestation,proto3" json:"attestation,omitempty"` +} + +func (m *QueryAttestationRequestByNonceResponse) Reset() { + *m = QueryAttestationRequestByNonceResponse{} +} +func (m *QueryAttestationRequestByNonceResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAttestationRequestByNonceResponse) ProtoMessage() {} +func (*QueryAttestationRequestByNonceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f3c1fd86445aad81, []int{3} +} +func (m *QueryAttestationRequestByNonceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAttestationRequestByNonceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAttestationRequestByNonceResponse.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 *QueryAttestationRequestByNonceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAttestationRequestByNonceResponse.Merge(m, src) +} +func (m *QueryAttestationRequestByNonceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAttestationRequestByNonceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAttestationRequestByNonceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAttestationRequestByNonceResponse proto.InternalMessageInfo + +func (m *QueryAttestationRequestByNonceResponse) GetAttestation() *types.Any { + if m != nil { + return m.Attestation + } + return nil +} + +// QueryLatestAttestationNonceRequest latest attestation nonce request +type QueryLatestAttestationNonceRequest struct { +} + +func (m *QueryLatestAttestationNonceRequest) Reset() { *m = QueryLatestAttestationNonceRequest{} } +func (m *QueryLatestAttestationNonceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryLatestAttestationNonceRequest) ProtoMessage() {} +func (*QueryLatestAttestationNonceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f3c1fd86445aad81, []int{4} +} +func (m *QueryLatestAttestationNonceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLatestAttestationNonceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLatestAttestationNonceRequest.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 *QueryLatestAttestationNonceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLatestAttestationNonceRequest.Merge(m, src) +} +func (m *QueryLatestAttestationNonceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryLatestAttestationNonceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLatestAttestationNonceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLatestAttestationNonceRequest proto.InternalMessageInfo + +// QueryLatestAttestationNonceResponse latest attestation nonce response +type QueryLatestAttestationNonceResponse struct { + Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` +} + +func (m *QueryLatestAttestationNonceResponse) Reset() { *m = QueryLatestAttestationNonceResponse{} } +func (m *QueryLatestAttestationNonceResponse) String() string { return proto.CompactTextString(m) } +func (*QueryLatestAttestationNonceResponse) ProtoMessage() {} +func (*QueryLatestAttestationNonceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f3c1fd86445aad81, []int{5} +} +func (m *QueryLatestAttestationNonceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLatestAttestationNonceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLatestAttestationNonceResponse.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 *QueryLatestAttestationNonceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLatestAttestationNonceResponse.Merge(m, src) +} +func (m *QueryLatestAttestationNonceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryLatestAttestationNonceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLatestAttestationNonceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLatestAttestationNonceResponse proto.InternalMessageInfo + +func (m *QueryLatestAttestationNonceResponse) GetNonce() uint64 { + if m != nil { + return m.Nonce + } + return 0 +} + +// QueryLastValsetRequestBeforeNonceRequest last Valset request before universal +// nonce request +type QueryLastValsetRequestBeforeNonceRequest struct { + Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` +} + +func (m *QueryLastValsetRequestBeforeNonceRequest) Reset() { + *m = QueryLastValsetRequestBeforeNonceRequest{} +} +func (m *QueryLastValsetRequestBeforeNonceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryLastValsetRequestBeforeNonceRequest) ProtoMessage() {} +func (*QueryLastValsetRequestBeforeNonceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f3c1fd86445aad81, []int{6} +} +func (m *QueryLastValsetRequestBeforeNonceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLastValsetRequestBeforeNonceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLastValsetRequestBeforeNonceRequest.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 *QueryLastValsetRequestBeforeNonceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLastValsetRequestBeforeNonceRequest.Merge(m, src) +} +func (m *QueryLastValsetRequestBeforeNonceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryLastValsetRequestBeforeNonceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLastValsetRequestBeforeNonceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLastValsetRequestBeforeNonceRequest proto.InternalMessageInfo + +func (m *QueryLastValsetRequestBeforeNonceRequest) GetNonce() uint64 { + if m != nil { + return m.Nonce + } + return 0 +} + +// QueryLastValsetRequestBeforeNonceResponse last Valset request before height +// response +type QueryLastValsetRequestBeforeNonceResponse struct { + Valset *Valset `protobuf:"bytes,1,opt,name=valset,proto3" json:"valset,omitempty"` +} + +func (m *QueryLastValsetRequestBeforeNonceResponse) Reset() { + *m = QueryLastValsetRequestBeforeNonceResponse{} +} +func (m *QueryLastValsetRequestBeforeNonceResponse) String() string { + return proto.CompactTextString(m) +} +func (*QueryLastValsetRequestBeforeNonceResponse) ProtoMessage() {} +func (*QueryLastValsetRequestBeforeNonceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f3c1fd86445aad81, []int{7} +} +func (m *QueryLastValsetRequestBeforeNonceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLastValsetRequestBeforeNonceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLastValsetRequestBeforeNonceResponse.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 *QueryLastValsetRequestBeforeNonceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLastValsetRequestBeforeNonceResponse.Merge(m, src) +} +func (m *QueryLastValsetRequestBeforeNonceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryLastValsetRequestBeforeNonceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLastValsetRequestBeforeNonceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLastValsetRequestBeforeNonceResponse proto.InternalMessageInfo + +func (m *QueryLastValsetRequestBeforeNonceResponse) GetValset() *Valset { + if m != nil { + return m.Valset + } + return nil +} + +// QueryLastUnbondingHeightRequest +type QueryLastUnbondingHeightRequest struct { +} + +func (m *QueryLastUnbondingHeightRequest) Reset() { *m = QueryLastUnbondingHeightRequest{} } +func (m *QueryLastUnbondingHeightRequest) String() string { return proto.CompactTextString(m) } +func (*QueryLastUnbondingHeightRequest) ProtoMessage() {} +func (*QueryLastUnbondingHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f3c1fd86445aad81, []int{8} +} +func (m *QueryLastUnbondingHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLastUnbondingHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLastUnbondingHeightRequest.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 *QueryLastUnbondingHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLastUnbondingHeightRequest.Merge(m, src) +} +func (m *QueryLastUnbondingHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryLastUnbondingHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLastUnbondingHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLastUnbondingHeightRequest proto.InternalMessageInfo + +// QueryLastUnbondingHeightResponse +type QueryLastUnbondingHeightResponse struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *QueryLastUnbondingHeightResponse) Reset() { *m = QueryLastUnbondingHeightResponse{} } +func (m *QueryLastUnbondingHeightResponse) String() string { return proto.CompactTextString(m) } +func (*QueryLastUnbondingHeightResponse) ProtoMessage() {} +func (*QueryLastUnbondingHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f3c1fd86445aad81, []int{9} +} +func (m *QueryLastUnbondingHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLastUnbondingHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLastUnbondingHeightResponse.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 *QueryLastUnbondingHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLastUnbondingHeightResponse.Merge(m, src) +} +func (m *QueryLastUnbondingHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryLastUnbondingHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLastUnbondingHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLastUnbondingHeightResponse proto.InternalMessageInfo + +func (m *QueryLastUnbondingHeightResponse) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func init() { + proto.RegisterType((*QueryParamsRequest)(nil), "qgb.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "qgb.QueryParamsResponse") + proto.RegisterType((*QueryAttestationRequestByNonceRequest)(nil), "qgb.QueryAttestationRequestByNonceRequest") + proto.RegisterType((*QueryAttestationRequestByNonceResponse)(nil), "qgb.QueryAttestationRequestByNonceResponse") + proto.RegisterType((*QueryLatestAttestationNonceRequest)(nil), "qgb.QueryLatestAttestationNonceRequest") + proto.RegisterType((*QueryLatestAttestationNonceResponse)(nil), "qgb.QueryLatestAttestationNonceResponse") + proto.RegisterType((*QueryLastValsetRequestBeforeNonceRequest)(nil), "qgb.QueryLastValsetRequestBeforeNonceRequest") + proto.RegisterType((*QueryLastValsetRequestBeforeNonceResponse)(nil), "qgb.QueryLastValsetRequestBeforeNonceResponse") + proto.RegisterType((*QueryLastUnbondingHeightRequest)(nil), "qgb.QueryLastUnbondingHeightRequest") + proto.RegisterType((*QueryLastUnbondingHeightResponse)(nil), "qgb.QueryLastUnbondingHeightResponse") +} + func init() { proto.RegisterFile("qgb/query.proto", fileDescriptor_f3c1fd86445aad81) } var fileDescriptor_f3c1fd86445aad81 = []byte{ - // 185 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0xce, 0x31, 0xaa, 0xc2, 0x40, - 0x10, 0x06, 0xe0, 0x84, 0xc7, 0x7b, 0x0f, 0xd2, 0x08, 0x96, 0x41, 0xf6, 0x00, 0x82, 0x19, 0xa2, - 0x37, 0xb0, 0xb3, 0xb4, 0xb5, 0x9b, 0x0d, 0xcb, 0xb8, 0x90, 0xec, 0x6c, 0xb2, 0x13, 0x31, 0xb7, - 0xf0, 0x58, 0x96, 0x29, 0x2d, 0x25, 0xb9, 0x88, 0x24, 0x01, 0xbb, 0xbf, 0xf8, 0xfe, 0x9f, 0x3f, - 0x59, 0xd5, 0xa4, 0xa1, 0x6e, 0x4d, 0xd3, 0x65, 0xbe, 0x61, 0xe1, 0xf5, 0x4f, 0x4d, 0x3a, 0xdd, - 0x10, 0x33, 0x95, 0x06, 0xd0, 0x5b, 0x40, 0xe7, 0x58, 0x50, 0x2c, 0xbb, 0xb0, 0x90, 0x74, 0x5b, - 0x70, 0xa8, 0x38, 0x80, 0xc6, 0x60, 0x96, 0x2e, 0xdc, 0x72, 0x6d, 0x04, 0x73, 0xf0, 0x48, 0xd6, - 0xcd, 0x78, 0xb1, 0xfb, 0xff, 0xe4, 0xf7, 0x3c, 0x89, 0xe3, 0xe9, 0x39, 0xa8, 0xb8, 0x1f, 0x54, - 0xfc, 0x1e, 0x54, 0xfc, 0x18, 0x55, 0xd4, 0x8f, 0x2a, 0x7a, 0x8d, 0x2a, 0xba, 0x00, 0x59, 0xb9, - 0xb6, 0x3a, 0x2b, 0xb8, 0x82, 0xc2, 0x94, 0x26, 0x88, 0x45, 0x6e, 0xe8, 0x9b, 0x77, 0xe8, 0x3d, - 0xdc, 0x61, 0x3a, 0x2a, 0x9d, 0x37, 0x41, 0xff, 0xcd, 0xd3, 0x87, 0x4f, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x2e, 0xe6, 0x68, 0x3e, 0xbc, 0x00, 0x00, 0x00, + // 603 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x94, 0x41, 0x6f, 0x12, 0x41, + 0x14, 0xc7, 0x59, 0x6d, 0x39, 0x0c, 0xb1, 0xea, 0x40, 0x68, 0xbb, 0x31, 0x5b, 0x9c, 0xd2, 0x4a, + 0x31, 0xdd, 0x49, 0xeb, 0x4d, 0x63, 0xd2, 0x72, 0xb2, 0x89, 0x51, 0x24, 0xd1, 0x83, 0x17, 0x33, + 0x8b, 0xd3, 0x61, 0x13, 0x98, 0x59, 0x76, 0x86, 0x46, 0x34, 0x5e, 0xfc, 0x00, 0xc6, 0xa4, 0x5f, + 0xc0, 0x0f, 0xe1, 0x87, 0x68, 0x3c, 0x35, 0xf1, 0xe2, 0xc9, 0x18, 0xf0, 0x83, 0x98, 0x9d, 0x99, + 0x05, 0x1a, 0xa0, 0x70, 0x9b, 0xf7, 0xe6, 0xff, 0xfe, 0xef, 0xf7, 0x98, 0xb7, 0x80, 0xdb, 0x5d, + 0x16, 0xe0, 0x6e, 0x8f, 0xc6, 0x7d, 0x3f, 0x8a, 0x85, 0x12, 0xf0, 0x66, 0x97, 0x05, 0xee, 0xdd, + 0x24, 0xcb, 0x28, 0xa7, 0x32, 0x94, 0x26, 0xef, 0x6a, 0xa1, 0xea, 0x47, 0x34, 0x4d, 0xdc, 0x63, + 0x42, 0xb0, 0x36, 0xc5, 0x24, 0x0a, 0x31, 0xe1, 0x5c, 0x28, 0xa2, 0x42, 0xc1, 0xd3, 0xdb, 0x6a, + 0x53, 0xc8, 0x8e, 0x90, 0x38, 0x20, 0x92, 0x1a, 0x7f, 0x7c, 0x76, 0x10, 0x50, 0x45, 0x0e, 0x70, + 0x44, 0x58, 0xc8, 0xb5, 0xd8, 0x6a, 0xd7, 0x12, 0xeb, 0x8e, 0x64, 0x69, 0x6d, 0x81, 0x09, 0x26, + 0xf4, 0x11, 0x27, 0x27, 0x9b, 0xdd, 0x34, 0x8e, 0xef, 0xcc, 0x85, 0x09, 0xd2, 0x2b, 0x8b, 0xa2, + 0xa3, 0xa0, 0x77, 0x8a, 0x09, 0xb7, 0xe3, 0xa0, 0x02, 0x80, 0xaf, 0x92, 0xee, 0x75, 0x12, 0x93, + 0x8e, 0x6c, 0xd0, 0x6e, 0x8f, 0x4a, 0x85, 0x8e, 0x40, 0xfe, 0x4a, 0x56, 0x46, 0x82, 0x4b, 0x0a, + 0xf7, 0x40, 0x36, 0xd2, 0x99, 0x0d, 0xa7, 0xe4, 0x54, 0x72, 0x87, 0x39, 0xbf, 0xcb, 0x02, 0xdf, + 0x88, 0x6a, 0x2b, 0x17, 0x7f, 0xb6, 0x32, 0x0d, 0x2b, 0x40, 0x4f, 0xc1, 0x8e, 0x76, 0x38, 0x56, + 0x8a, 0x4a, 0x33, 0xba, 0x35, 0xaf, 0xf5, 0x5f, 0x08, 0xde, 0xa4, 0x36, 0x82, 0x05, 0xb0, 0xca, + 0x93, 0x58, 0x5b, 0xae, 0x34, 0x4c, 0x80, 0xfa, 0x60, 0x77, 0x51, 0xb9, 0x65, 0x7a, 0x09, 0x72, + 0x64, 0x2c, 0xb2, 0x60, 0x05, 0xdf, 0x4c, 0xec, 0xa7, 0x13, 0xfb, 0xc7, 0xbc, 0x5f, 0x5b, 0xff, + 0xf9, 0x63, 0x3f, 0x3f, 0xed, 0x78, 0xd2, 0x98, 0x74, 0x40, 0x65, 0x80, 0x74, 0xeb, 0xe7, 0x24, + 0xc9, 0x4d, 0xc8, 0x27, 0xb1, 0xd1, 0x13, 0xb0, 0x7d, 0xad, 0xca, 0xd2, 0xcd, 0x9e, 0xee, 0x08, + 0x54, 0x6c, 0xb1, 0x54, 0x6f, 0x48, 0x5b, 0x52, 0x95, 0x0e, 0x47, 0x4f, 0x45, 0x4c, 0x97, 0xf8, + 0x7d, 0xea, 0x60, 0x6f, 0x09, 0x07, 0x0b, 0xb1, 0x0d, 0xb2, 0x67, 0x5a, 0x73, 0xe5, 0xd9, 0x6c, + 0x99, 0xbd, 0x42, 0xf7, 0xc1, 0xd6, 0xc8, 0xf1, 0x35, 0x0f, 0x04, 0x7f, 0x1f, 0x72, 0xf6, 0x8c, + 0x86, 0xac, 0x95, 0x5a, 0xa3, 0xc7, 0xa0, 0x34, 0x5f, 0x62, 0x7b, 0x15, 0x41, 0xb6, 0xa5, 0x33, + 0x96, 0xd7, 0x46, 0x87, 0x5f, 0x57, 0xc0, 0xaa, 0x2e, 0x86, 0x75, 0x90, 0x35, 0x1b, 0x03, 0xd7, + 0x35, 0xc7, 0xf4, 0xfa, 0xb9, 0x1b, 0xd3, 0x17, 0xc6, 0x1e, 0xe5, 0xbf, 0xfc, 0xfa, 0x77, 0x7e, + 0xe3, 0x16, 0xcc, 0xe1, 0xe4, 0x9b, 0x30, 0xbb, 0x06, 0xbf, 0x3b, 0x60, 0x73, 0xee, 0xa2, 0xc0, + 0xea, 0xd8, 0x6c, 0xd1, 0x32, 0xba, 0x0f, 0x97, 0xd2, 0x5a, 0x96, 0xaa, 0x66, 0x29, 0x43, 0xa4, + 0x59, 0x26, 0x56, 0x48, 0xe2, 0xd8, 0x54, 0x48, 0xfc, 0x49, 0x3f, 0xd7, 0x67, 0x78, 0xee, 0x80, + 0xe2, 0xec, 0x55, 0x81, 0x0f, 0xc6, 0x3d, 0xaf, 0x5d, 0x39, 0xb7, 0xb2, 0x58, 0x68, 0xc9, 0x76, + 0x35, 0x59, 0x09, 0x7a, 0xd3, 0x64, 0x9a, 0x07, 0xb7, 0x75, 0x3d, 0xfc, 0x08, 0xf2, 0x33, 0xde, + 0x12, 0x96, 0x27, 0x1b, 0xcd, 0xdb, 0x06, 0x77, 0x67, 0x81, 0xca, 0xb2, 0x14, 0x35, 0xcb, 0x1d, + 0xb8, 0xa6, 0x59, 0x7a, 0xa9, 0xaa, 0x76, 0x72, 0x31, 0xf0, 0x9c, 0xcb, 0x81, 0xe7, 0xfc, 0x1d, + 0x78, 0xce, 0xb7, 0xa1, 0x97, 0xb9, 0x1c, 0x7a, 0x99, 0xdf, 0x43, 0x2f, 0xf3, 0x16, 0xb3, 0x50, + 0xb5, 0x7a, 0x81, 0xdf, 0x14, 0x1d, 0xdc, 0xa4, 0x6d, 0x2a, 0x55, 0x48, 0x44, 0xcc, 0x46, 0xe7, + 0x7d, 0x12, 0x45, 0xf8, 0x03, 0x1e, 0xfd, 0xdf, 0x06, 0x59, 0xfd, 0x95, 0x3f, 0xfa, 0x1f, 0x00, + 0x00, 0xff, 0xff, 0x2a, 0x88, 0x0b, 0x96, 0xac, 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -55,6 +540,15 @@ const _ = grpc.SupportPackageIsVersion4 // // 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 { + // Params queries the current parameters for the qgb module + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) + // AttestationRequestByNonce queries attestation request by nonce. + // Returns nil if not found. + AttestationRequestByNonce(ctx context.Context, in *QueryAttestationRequestByNonceRequest, opts ...grpc.CallOption) (*QueryAttestationRequestByNonceResponse, error) + // LatestAttestationNonce queries latest attestation nonce. + LatestAttestationNonce(ctx context.Context, in *QueryLatestAttestationNonceRequest, opts ...grpc.CallOption) (*QueryLatestAttestationNonceResponse, error) + // LastUnbondingHeight returns the last unbonding height + LastUnbondingHeight(ctx context.Context, in *QueryLastUnbondingHeightRequest, opts ...grpc.CallOption) (*QueryLastUnbondingHeightResponse, error) } type queryClient struct { @@ -65,22 +559,1348 @@ 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, "/qgb.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AttestationRequestByNonce(ctx context.Context, in *QueryAttestationRequestByNonceRequest, opts ...grpc.CallOption) (*QueryAttestationRequestByNonceResponse, error) { + out := new(QueryAttestationRequestByNonceResponse) + err := c.cc.Invoke(ctx, "/qgb.Query/AttestationRequestByNonce", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) LatestAttestationNonce(ctx context.Context, in *QueryLatestAttestationNonceRequest, opts ...grpc.CallOption) (*QueryLatestAttestationNonceResponse, error) { + out := new(QueryLatestAttestationNonceResponse) + err := c.cc.Invoke(ctx, "/qgb.Query/LatestAttestationNonce", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) LastUnbondingHeight(ctx context.Context, in *QueryLastUnbondingHeightRequest, opts ...grpc.CallOption) (*QueryLastUnbondingHeightResponse, error) { + out := new(QueryLastUnbondingHeightResponse) + err := c.cc.Invoke(ctx, "/qgb.Query/LastUnbondingHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { + // Params queries the current parameters for the qgb module + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) + // AttestationRequestByNonce queries attestation request by nonce. + // Returns nil if not found. + AttestationRequestByNonce(context.Context, *QueryAttestationRequestByNonceRequest) (*QueryAttestationRequestByNonceResponse, error) + // LatestAttestationNonce queries latest attestation nonce. + LatestAttestationNonce(context.Context, *QueryLatestAttestationNonceRequest) (*QueryLatestAttestationNonceResponse, error) + // LastUnbondingHeight returns the last unbonding height + LastUnbondingHeight(context.Context, *QueryLastUnbondingHeightRequest) (*QueryLastUnbondingHeightResponse, 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 (*UnimplementedQueryServer) AttestationRequestByNonce(ctx context.Context, req *QueryAttestationRequestByNonceRequest) (*QueryAttestationRequestByNonceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AttestationRequestByNonce not implemented") +} +func (*UnimplementedQueryServer) LatestAttestationNonce(ctx context.Context, req *QueryLatestAttestationNonceRequest) (*QueryLatestAttestationNonceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method LatestAttestationNonce not implemented") +} +func (*UnimplementedQueryServer) LastUnbondingHeight(ctx context.Context, req *QueryLastUnbondingHeightRequest) (*QueryLastUnbondingHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method LastUnbondingHeight 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: "/qgb.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AttestationRequestByNonce_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAttestationRequestByNonceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AttestationRequestByNonce(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/qgb.Query/AttestationRequestByNonce", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AttestationRequestByNonce(ctx, req.(*QueryAttestationRequestByNonceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_LatestAttestationNonce_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryLatestAttestationNonceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).LatestAttestationNonce(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/qgb.Query/LatestAttestationNonce", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).LatestAttestationNonce(ctx, req.(*QueryLatestAttestationNonceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_LastUnbondingHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryLastUnbondingHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).LastUnbondingHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/qgb.Query/LastUnbondingHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).LastUnbondingHeight(ctx, req.(*QueryLastUnbondingHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "qgb.Query", HandlerType: (*QueryServer)(nil), - Methods: []grpc.MethodDesc{}, - Streams: []grpc.StreamDesc{}, - Metadata: "qgb/query.proto", + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + { + MethodName: "AttestationRequestByNonce", + Handler: _Query_AttestationRequestByNonce_Handler, + }, + { + MethodName: "LatestAttestationNonce", + Handler: _Query_LatestAttestationNonce_Handler, + }, + { + MethodName: "LastUnbondingHeight", + Handler: _Query_LastUnbondingHeight_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "qgb/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 (m *QueryAttestationRequestByNonceRequest) 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 *QueryAttestationRequestByNonceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAttestationRequestByNonceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Nonce != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Nonce)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryAttestationRequestByNonceResponse) 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 *QueryAttestationRequestByNonceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAttestationRequestByNonceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Attestation != nil { + { + size, err := m.Attestation.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryLatestAttestationNonceRequest) 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 *QueryLatestAttestationNonceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLatestAttestationNonceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryLatestAttestationNonceResponse) 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 *QueryLatestAttestationNonceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLatestAttestationNonceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Nonce != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Nonce)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryLastValsetRequestBeforeNonceRequest) 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 *QueryLastValsetRequestBeforeNonceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLastValsetRequestBeforeNonceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Nonce != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Nonce)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryLastValsetRequestBeforeNonceResponse) 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 *QueryLastValsetRequestBeforeNonceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLastValsetRequestBeforeNonceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Valset != nil { + { + size, err := m.Valset.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryLastUnbondingHeightRequest) 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 *QueryLastUnbondingHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLastUnbondingHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryLastUnbondingHeightResponse) 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 *QueryLastUnbondingHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLastUnbondingHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + 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 (m *QueryAttestationRequestByNonceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Nonce != 0 { + n += 1 + sovQuery(uint64(m.Nonce)) + } + return n +} + +func (m *QueryAttestationRequestByNonceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Attestation != nil { + l = m.Attestation.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryLatestAttestationNonceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryLatestAttestationNonceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Nonce != 0 { + n += 1 + sovQuery(uint64(m.Nonce)) + } + return n +} + +func (m *QueryLastValsetRequestBeforeNonceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Nonce != 0 { + n += 1 + sovQuery(uint64(m.Nonce)) + } + return n +} + +func (m *QueryLastValsetRequestBeforeNonceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Valset != nil { + l = m.Valset.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryLastUnbondingHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryLastUnbondingHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovQuery(uint64(m.Height)) + } + 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 (m *QueryAttestationRequestByNonceRequest) 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: QueryAttestationRequestByNonceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAttestationRequestByNonceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType) + } + m.Nonce = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Nonce |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAttestationRequestByNonceResponse) 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: QueryAttestationRequestByNonceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAttestationRequestByNonceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Attestation", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Attestation == nil { + m.Attestation = &types.Any{} + } + if err := m.Attestation.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } +func (m *QueryLatestAttestationNonceRequest) 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: QueryLatestAttestationNonceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLatestAttestationNonceRequest: 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 *QueryLatestAttestationNonceResponse) 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: QueryLatestAttestationNonceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLatestAttestationNonceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType) + } + m.Nonce = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Nonce |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryLastValsetRequestBeforeNonceRequest) 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: QueryLastValsetRequestBeforeNonceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLastValsetRequestBeforeNonceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType) + } + m.Nonce = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Nonce |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryLastValsetRequestBeforeNonceResponse) 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: QueryLastValsetRequestBeforeNonceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLastValsetRequestBeforeNonceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Valset", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Valset == nil { + m.Valset = &Valset{} + } + if err := m.Valset.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryLastUnbondingHeightRequest) 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: QueryLastUnbondingHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLastUnbondingHeightRequest: 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 *QueryLastUnbondingHeightResponse) 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: QueryLastUnbondingHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLastUnbondingHeightResponse: 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 ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func 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/qgb/types/query.pb.gw.go b/x/qgb/types/query.pb.gw.go new file mode 100644 index 0000000000..26bd54bd0c --- /dev/null +++ b/x/qgb/types/query.pb.gw.go @@ -0,0 +1,384 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: qgb/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 + +} + +func request_Query_AttestationRequestByNonce_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAttestationRequestByNonceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["nonce"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "nonce") + } + + protoReq.Nonce, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "nonce", err) + } + + msg, err := client.AttestationRequestByNonce(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AttestationRequestByNonce_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAttestationRequestByNonceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["nonce"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "nonce") + } + + protoReq.Nonce, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "nonce", err) + } + + msg, err := server.AttestationRequestByNonce(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_LatestAttestationNonce_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryLatestAttestationNonceRequest + var metadata runtime.ServerMetadata + + msg, err := client.LatestAttestationNonce(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_LatestAttestationNonce_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryLatestAttestationNonceRequest + var metadata runtime.ServerMetadata + + msg, err := server.LatestAttestationNonce(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_LastUnbondingHeight_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryLastUnbondingHeightRequest + var metadata runtime.ServerMetadata + + msg, err := client.LastUnbondingHeight(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_LastUnbondingHeight_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryLastUnbondingHeightRequest + var metadata runtime.ServerMetadata + + msg, err := server.LastUnbondingHeight(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()...) + + }) + + mux.Handle("GET", pattern_Query_AttestationRequestByNonce_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_AttestationRequestByNonce_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_AttestationRequestByNonce_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_LatestAttestationNonce_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_LatestAttestationNonce_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_LatestAttestationNonce_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_LastUnbondingHeight_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_LastUnbondingHeight_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_LastUnbondingHeight_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()...) + + }) + + mux.Handle("GET", pattern_Query_AttestationRequestByNonce_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_AttestationRequestByNonce_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_AttestationRequestByNonce_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_LatestAttestationNonce_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_LatestAttestationNonce_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_LatestAttestationNonce_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_LastUnbondingHeight_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_LastUnbondingHeight_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_LastUnbondingHeight_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}, []string{"qgb", "params"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_AttestationRequestByNonce_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"qgb", "attestations", "requests", "nonce"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_LatestAttestationNonce_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"qgb", "attestations", "nonce", "latest"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_LastUnbondingHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"qgb", "unbonding"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_AttestationRequestByNonce_0 = runtime.ForwardResponseMessage + + forward_Query_LatestAttestationNonce_0 = runtime.ForwardResponseMessage + + forward_Query_LastUnbondingHeight_0 = runtime.ForwardResponseMessage +) diff --git a/x/qgb/types/types.go b/x/qgb/types/types.go new file mode 100644 index 0000000000..58cb59be4f --- /dev/null +++ b/x/qgb/types/types.go @@ -0,0 +1,8 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// UInt64Bytes uses the SDK byte marshaling to encode a uint64. +func UInt64Bytes(n uint64) []byte { + return sdk.Uint64ToBigEndian(n) +} diff --git a/x/qgb/types/types.pb.go b/x/qgb/types/types.pb.go new file mode 100644 index 0000000000..982ec7cc4e --- /dev/null +++ b/x/qgb/types/types.pb.go @@ -0,0 +1,860 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: qgb/types.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// BridgeValidator represents a validator's ETH address and its power +type BridgeValidator struct { + // Voting power of the validator. + Power uint64 `protobuf:"varint,1,opt,name=power,proto3" json:"power,omitempty"` + // Ethereum address that will be used by the validator to sign messages. + EthereumAddress string `protobuf:"bytes,2,opt,name=ethereum_address,json=ethereumAddress,proto3" json:"ethereum_address,omitempty"` +} + +func (m *BridgeValidator) Reset() { *m = BridgeValidator{} } +func (m *BridgeValidator) String() string { return proto.CompactTextString(m) } +func (*BridgeValidator) ProtoMessage() {} +func (*BridgeValidator) Descriptor() ([]byte, []int) { + return fileDescriptor_4b33a58818ab2113, []int{0} +} +func (m *BridgeValidator) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BridgeValidator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BridgeValidator.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 *BridgeValidator) XXX_Merge(src proto.Message) { + xxx_messageInfo_BridgeValidator.Merge(m, src) +} +func (m *BridgeValidator) XXX_Size() int { + return m.Size() +} +func (m *BridgeValidator) XXX_DiscardUnknown() { + xxx_messageInfo_BridgeValidator.DiscardUnknown(m) +} + +var xxx_messageInfo_BridgeValidator proto.InternalMessageInfo + +func (m *BridgeValidator) GetPower() uint64 { + if m != nil { + return m.Power + } + return 0 +} + +func (m *BridgeValidator) GetEthereumAddress() string { + if m != nil { + return m.EthereumAddress + } + return "" +} + +// Valset is the Ethereum Bridge Multsig Set, each qgb validator also +// maintains an ETH key to sign messages, these are used to check signatures on +// ETH because of the significant gas savings +type Valset struct { + // Universal nonce defined under: + // https://github.com/celestiaorg/celestia-app/pull/464 + Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` + // List of BridgeValidator containing the current validator set. + Members []BridgeValidator `protobuf:"bytes,2,rep,name=members,proto3" json:"members"` + // Current chain height + Height uint64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *Valset) Reset() { *m = Valset{} } +func (m *Valset) String() string { return proto.CompactTextString(m) } +func (*Valset) ProtoMessage() {} +func (*Valset) Descriptor() ([]byte, []int) { + return fileDescriptor_4b33a58818ab2113, []int{1} +} +func (m *Valset) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Valset) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Valset.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 *Valset) XXX_Merge(src proto.Message) { + xxx_messageInfo_Valset.Merge(m, src) +} +func (m *Valset) XXX_Size() int { + return m.Size() +} +func (m *Valset) XXX_DiscardUnknown() { + xxx_messageInfo_Valset.DiscardUnknown(m) +} + +var xxx_messageInfo_Valset proto.InternalMessageInfo + +func (m *Valset) GetNonce() uint64 { + if m != nil { + return m.Nonce + } + return 0 +} + +func (m *Valset) GetMembers() []BridgeValidator { + if m != nil { + return m.Members + } + return nil +} + +func (m *Valset) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +// DataCommitment is the data commitment request message that will be signed +// using orchestrators. +// It does not contain a `commitment` field as this message will be created +// inside the state machine and it doesn't make sense to ask tendermint for the +// commitment there. +type DataCommitment struct { + // Universal nonce defined under: + // https://github.com/celestiaorg/celestia-app/pull/464 + Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` + // First block defining the ordered set of blocks used to create the + // commitment. + BeginBlock uint64 `protobuf:"varint,2,opt,name=begin_block,json=beginBlock,proto3" json:"begin_block,omitempty"` + // Last block defining the ordered set of blocks used to create the + // commitment. + EndBlock uint64 `protobuf:"varint,3,opt,name=end_block,json=endBlock,proto3" json:"end_block,omitempty"` +} + +func (m *DataCommitment) Reset() { *m = DataCommitment{} } +func (m *DataCommitment) String() string { return proto.CompactTextString(m) } +func (*DataCommitment) ProtoMessage() {} +func (*DataCommitment) Descriptor() ([]byte, []int) { + return fileDescriptor_4b33a58818ab2113, []int{2} +} +func (m *DataCommitment) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DataCommitment) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DataCommitment.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 *DataCommitment) XXX_Merge(src proto.Message) { + xxx_messageInfo_DataCommitment.Merge(m, src) +} +func (m *DataCommitment) XXX_Size() int { + return m.Size() +} +func (m *DataCommitment) XXX_DiscardUnknown() { + xxx_messageInfo_DataCommitment.DiscardUnknown(m) +} + +var xxx_messageInfo_DataCommitment proto.InternalMessageInfo + +func (m *DataCommitment) GetNonce() uint64 { + if m != nil { + return m.Nonce + } + return 0 +} + +func (m *DataCommitment) GetBeginBlock() uint64 { + if m != nil { + return m.BeginBlock + } + return 0 +} + +func (m *DataCommitment) GetEndBlock() uint64 { + if m != nil { + return m.EndBlock + } + return 0 +} + +func init() { + proto.RegisterType((*BridgeValidator)(nil), "qgb.BridgeValidator") + proto.RegisterType((*Valset)(nil), "qgb.Valset") + proto.RegisterType((*DataCommitment)(nil), "qgb.DataCommitment") +} + +func init() { proto.RegisterFile("qgb/types.proto", fileDescriptor_4b33a58818ab2113) } + +var fileDescriptor_4b33a58818ab2113 = []byte{ + // 357 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xb1, 0x6f, 0xda, 0x40, + 0x14, 0xc6, 0xed, 0x42, 0x69, 0x39, 0xa4, 0x52, 0xb9, 0xa8, 0xa5, 0x54, 0x32, 0x88, 0x89, 0x0e, + 0xd8, 0x52, 0x9b, 0x29, 0x1b, 0x4e, 0x16, 0x56, 0x0f, 0x0c, 0x59, 0xd0, 0x9d, 0xfd, 0x74, 0x3e, + 0xc5, 0xe7, 0xb3, 0xef, 0x1e, 0x4a, 0x32, 0x64, 0xcc, 0x9e, 0x3f, 0x26, 0x7f, 0x04, 0x23, 0xca, + 0x94, 0x29, 0x8a, 0xe0, 0x1f, 0x89, 0x6c, 0x03, 0x43, 0x24, 0xb6, 0xf7, 0x7d, 0xbf, 0xd3, 0xf7, + 0xde, 0xe9, 0x23, 0xdd, 0x82, 0x33, 0x1f, 0xef, 0x72, 0x30, 0x5e, 0xae, 0x15, 0x2a, 0xa7, 0x51, + 0x70, 0x36, 0xe8, 0x71, 0xc5, 0x55, 0xa5, 0xfd, 0x72, 0xaa, 0xd1, 0xe0, 0x77, 0xa4, 0x8c, 0x54, + 0x66, 0x59, 0x83, 0x5a, 0xd4, 0x68, 0x1c, 0x92, 0x6e, 0xa0, 0x45, 0xcc, 0x61, 0x41, 0x53, 0x11, + 0x53, 0x54, 0xda, 0xe9, 0x91, 0xcf, 0xb9, 0xba, 0x01, 0xdd, 0xb7, 0x47, 0xf6, 0xa4, 0x19, 0xd6, + 0xc2, 0xf9, 0x4b, 0xbe, 0x03, 0x26, 0xa0, 0x61, 0x25, 0x97, 0x34, 0x8e, 0x35, 0x18, 0xd3, 0xff, + 0x34, 0xb2, 0x27, 0xed, 0xb0, 0x7b, 0xf0, 0x67, 0xb5, 0x3d, 0x7e, 0xb0, 0x49, 0x6b, 0x41, 0x53, + 0x03, 0x58, 0x66, 0x65, 0x2a, 0x8b, 0xe0, 0x90, 0x55, 0x09, 0xe7, 0x8c, 0x7c, 0x91, 0x20, 0x19, + 0xe8, 0x32, 0xa2, 0x31, 0xe9, 0xfc, 0xeb, 0x79, 0x05, 0x67, 0xde, 0x87, 0x43, 0x82, 0xe6, 0xfa, + 0x75, 0x68, 0x85, 0x87, 0xa7, 0xce, 0x4f, 0xd2, 0x4a, 0x40, 0xf0, 0x04, 0xfb, 0x8d, 0x2a, 0x6c, + 0xaf, 0xce, 0x7f, 0x3d, 0x3f, 0x4d, 0x7f, 0xcc, 0x10, 0xc1, 0x20, 0x45, 0xa1, 0xb2, 0x10, 0x8a, + 0x15, 0x18, 0x9c, 0x8f, 0xef, 0xc9, 0xb7, 0x4b, 0x8a, 0xf4, 0x42, 0x49, 0x29, 0x50, 0x42, 0x76, + 0xea, 0x9c, 0x21, 0xe9, 0x30, 0xe0, 0x22, 0x5b, 0xb2, 0x54, 0x45, 0xd7, 0xd5, 0xaf, 0x9a, 0x21, + 0xa9, 0xac, 0xa0, 0x74, 0x9c, 0x3f, 0xa4, 0x0d, 0x59, 0xbc, 0xc7, 0xf5, 0xf2, 0xaf, 0x90, 0xc5, + 0x15, 0x3c, 0xb9, 0x3e, 0x98, 0xaf, 0xb7, 0xae, 0xbd, 0xd9, 0xba, 0xf6, 0xdb, 0xd6, 0xb5, 0x1f, + 0x77, 0xae, 0xb5, 0xd9, 0xb9, 0xd6, 0xcb, 0xce, 0xb5, 0xae, 0x7c, 0x2e, 0x30, 0x59, 0x31, 0x2f, + 0x52, 0xd2, 0x8f, 0x20, 0x05, 0x83, 0x82, 0x2a, 0xcd, 0x8f, 0xf3, 0x94, 0xe6, 0xb9, 0x7f, 0xeb, + 0x1f, 0x1b, 0x66, 0xad, 0xaa, 0xac, 0xff, 0xef, 0x01, 0x00, 0x00, 0xff, 0xff, 0x11, 0x58, 0x15, + 0xb4, 0xf5, 0x01, 0x00, 0x00, +} + +func (m *BridgeValidator) 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 *BridgeValidator) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BridgeValidator) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.EthereumAddress) > 0 { + i -= len(m.EthereumAddress) + copy(dAtA[i:], m.EthereumAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.EthereumAddress))) + i-- + dAtA[i] = 0x12 + } + if m.Power != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Power)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Valset) 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 *Valset) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Valset) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x18 + } + if len(m.Members) > 0 { + for iNdEx := len(m.Members) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Members[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Nonce != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Nonce)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *DataCommitment) 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 *DataCommitment) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DataCommitment) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.EndBlock != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.EndBlock)) + i-- + dAtA[i] = 0x18 + } + if m.BeginBlock != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.BeginBlock)) + i-- + dAtA[i] = 0x10 + } + if m.Nonce != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Nonce)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *BridgeValidator) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Power != 0 { + n += 1 + sovTypes(uint64(m.Power)) + } + l = len(m.EthereumAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Valset) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Nonce != 0 { + n += 1 + sovTypes(uint64(m.Nonce)) + } + if len(m.Members) > 0 { + for _, e := range m.Members { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *DataCommitment) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Nonce != 0 { + n += 1 + sovTypes(uint64(m.Nonce)) + } + if m.BeginBlock != 0 { + n += 1 + sovTypes(uint64(m.BeginBlock)) + } + if m.EndBlock != 0 { + n += 1 + sovTypes(uint64(m.EndBlock)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *BridgeValidator) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BridgeValidator: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BridgeValidator: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Power", wireType) + } + m.Power = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Power |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EthereumAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.EthereumAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Valset) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Valset: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Valset: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType) + } + m.Nonce = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Nonce |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Members = append(m.Members, BridgeValidator{}) + if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + 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 ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DataCommitment) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DataCommitment: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DataCommitment: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType) + } + m.Nonce = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Nonce |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + m.BeginBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BeginBlock |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + m.EndBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.EndBlock |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/qgb/types/types_test.go b/x/qgb/types/types_test.go new file mode 100644 index 0000000000..1d7c06ea1f --- /dev/null +++ b/x/qgb/types/types_test.go @@ -0,0 +1,151 @@ +package types_test + +import ( + "bytes" + mrand "math/rand" + "testing" + + "github.com/celestiaorg/celestia-app/x/qgb/types" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +func TestValsetPowerDiff(t *testing.T) { + specs := map[string]struct { + start types.BridgeValidators + diff types.BridgeValidators + exp float64 + }{ + "no diff": { + start: types.BridgeValidators{ + {Power: 1, EthereumAddress: "0x479FFc856Cdfa0f5D1AE6Fa61915b01351A7773D"}, + {Power: 2, EthereumAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"}, + {Power: 3, EthereumAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"}, + }, + diff: types.BridgeValidators{ + {Power: 1, EthereumAddress: "0x479FFc856Cdfa0f5D1AE6Fa61915b01351A7773D"}, + {Power: 2, EthereumAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"}, + {Power: 3, EthereumAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"}, + }, + exp: 0.0, + }, + "one": { + start: types.BridgeValidators{ + {Power: 1073741823, EthereumAddress: "0x479FFc856Cdfa0f5D1AE6Fa61915b01351A7773D"}, + {Power: 1073741823, EthereumAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"}, + {Power: 2147483646, EthereumAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"}, + }, + diff: types.BridgeValidators{ + {Power: 858993459, EthereumAddress: "0x479FFc856Cdfa0f5D1AE6Fa61915b01351A7773D"}, + {Power: 858993459, EthereumAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"}, + {Power: 2576980377, EthereumAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"}, + }, + exp: 0.2, + }, + "real world": { + start: types.BridgeValidators{ + {Power: 678509841, EthereumAddress: "0x6db48cBBCeD754bDc760720e38E456144e83269b"}, + {Power: 671724742, EthereumAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"}, + {Power: 685294939, EthereumAddress: "0x479FFc856Cdfa0f5D1AE6Fa61915b01351A7773D"}, + {Power: 671724742, EthereumAddress: "0x0A7254b318dd742A3086882321C27779B4B642a6"}, + {Power: 671724742, EthereumAddress: "0x454330deAaB759468065d08F2b3B0562caBe1dD1"}, + {Power: 617443955, EthereumAddress: "0x3511A211A6759d48d107898302042d1301187BA9"}, + {Power: 6785098, EthereumAddress: "0x37A0603dA2ff6377E5C7f75698dabA8EE4Ba97B8"}, + {Power: 291759231, EthereumAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"}, + }, + diff: types.BridgeValidators{ + {Power: 642345266, EthereumAddress: "0x479FFc856Cdfa0f5D1AE6Fa61915b01351A7773D"}, + {Power: 678509841, EthereumAddress: "0x6db48cBBCeD754bDc760720e38E456144e83269b"}, + {Power: 671724742, EthereumAddress: "0x0A7254b318dd742A3086882321C27779B4B642a6"}, + {Power: 671724742, EthereumAddress: "0x454330deAaB759468065d08F2b3B0562caBe1dD1"}, + {Power: 671724742, EthereumAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"}, + {Power: 617443955, EthereumAddress: "0x3511A211A6759d48d107898302042d1301187BA9"}, + {Power: 291759231, EthereumAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"}, + {Power: 6785098, EthereumAddress: "0x37A0603dA2ff6377E5C7f75698dabA8EE4Ba97B8"}, + }, + exp: 0.010000000011641532, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + startInternal, _ := spec.start.ToInternal() + diffInternal, _ := spec.diff.ToInternal() + assert.Equal(t, spec.exp, startInternal.PowerDiff(*diffInternal)) + }) + } +} + +func TestValsetSort(t *testing.T) { + specs := map[string]struct { + src types.BridgeValidators + exp types.BridgeValidators + }{ + "by power desc": { + src: types.BridgeValidators{ + {Power: 1, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(3)}, 20)).String()}, + {Power: 2, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(1)}, 20)).String()}, + {Power: 3, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(2)}, 20)).String()}, + }, + exp: types.BridgeValidators{ + {Power: 3, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(2)}, 20)).String()}, + {Power: 2, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(1)}, 20)).String()}, + {Power: 1, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(3)}, 20)).String()}, + }, + }, + "by eth addr on same power": { + src: types.BridgeValidators{ + {Power: 1, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(2)}, 20)).String()}, + {Power: 1, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(1)}, 20)).String()}, + {Power: 1, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(3)}, 20)).String()}, + }, + exp: types.BridgeValidators{ + {Power: 1, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(1)}, 20)).String()}, + {Power: 1, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(2)}, 20)).String()}, + {Power: 1, EthereumAddress: gethcommon.BytesToAddress(bytes.Repeat([]byte{byte(3)}, 20)).String()}, + }, + }, + // if you're thinking about changing this due to a change in the sorting algorithm + // you MUST go change this in gravity_utils/types.rs as well. You will also break all + // bridges in production when they try to migrate so use extreme caution! + "real world": { + src: types.BridgeValidators{ + {Power: 678509841, EthereumAddress: "0x6db48cBBCeD754bDc760720e38E456144e83269b"}, + {Power: 671724742, EthereumAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"}, + {Power: 685294939, EthereumAddress: "0x479FFc856Cdfa0f5D1AE6Fa61915b01351A7773D"}, + {Power: 671724742, EthereumAddress: "0x0A7254b318dd742A3086882321C27779B4B642a6"}, + {Power: 671724742, EthereumAddress: "0x454330deAaB759468065d08F2b3B0562caBe1dD1"}, + {Power: 617443955, EthereumAddress: "0x3511A211A6759d48d107898302042d1301187BA9"}, + {Power: 6785098, EthereumAddress: "0x37A0603dA2ff6377E5C7f75698dabA8EE4Ba97B8"}, + {Power: 291759231, EthereumAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"}, + }, + exp: types.BridgeValidators{ + {Power: 685294939, EthereumAddress: "0x479FFc856Cdfa0f5D1AE6Fa61915b01351A7773D"}, + {Power: 678509841, EthereumAddress: "0x6db48cBBCeD754bDc760720e38E456144e83269b"}, + {Power: 671724742, EthereumAddress: "0x0A7254b318dd742A3086882321C27779B4B642a6"}, + {Power: 671724742, EthereumAddress: "0x454330deAaB759468065d08F2b3B0562caBe1dD1"}, + {Power: 671724742, EthereumAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"}, + {Power: 617443955, EthereumAddress: "0x3511A211A6759d48d107898302042d1301187BA9"}, + {Power: 291759231, EthereumAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"}, + {Power: 6785098, EthereumAddress: "0x37A0603dA2ff6377E5C7f75698dabA8EE4Ba97B8"}, + }, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + srcInternal, _ := spec.src.ToInternal() + expInternal, _ := spec.exp.ToInternal() + srcInternal.Sort() + assert.Equal(t, srcInternal, expInternal) + shuffled := shuffled(*srcInternal) + shuffled.Sort() + assert.Equal(t, shuffled, *expInternal) + }) + } +} + +func shuffled(v types.InternalBridgeValidators) types.InternalBridgeValidators { + mrand.Shuffle(len(v), func(i, j int) { + v[i], v[j] = v[j], v[i] + }) + return v +} diff --git a/x/qgb/types/validator.go b/x/qgb/types/validator.go new file mode 100644 index 0000000000..5fa840db23 --- /dev/null +++ b/x/qgb/types/validator.go @@ -0,0 +1,180 @@ +package types + +import ( + "bytes" + math "math" + "sort" + + "github.com/ethereum/go-ethereum/common" + + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// ToInternal transforms a BridgeValidator into its fully validated internal type. +func (b BridgeValidator) ToInternal() (*InternalBridgeValidator, error) { + return NewInternalBridgeValidator(b) +} + +// BridgeValidators is the sorted set of validator data for Ethereum bridge MultiSig set. +type BridgeValidators []BridgeValidator + +func (b BridgeValidators) ToInternal() (*InternalBridgeValidators, error) { + ret := make(InternalBridgeValidators, len(b)) + for i := range b { + ibv, err := NewInternalBridgeValidator(b[i]) + if err != nil { + return nil, sdkerrors.Wrapf(err, "member %d", i) + } + ret[i] = ibv + } + return &ret, nil +} + +// Bridge Validator but with validated EthereumAddress. +type InternalBridgeValidator struct { + Power uint64 + EthereumAddress common.Address +} + +func NewInternalBridgeValidator(bridgeValidator BridgeValidator) (*InternalBridgeValidator, error) { + if !common.IsHexAddress(bridgeValidator.EthereumAddress) { + return nil, stakingtypes.ErrEthAddressNotHex + } + validatorEthAddr := common.HexToAddress(bridgeValidator.EthereumAddress) + i := &InternalBridgeValidator{ + Power: bridgeValidator.Power, + EthereumAddress: validatorEthAddr, + } + if err := i.ValidateBasic(); err != nil { + return nil, sdkerrors.Wrap(err, "invalid bridge validator") + } + return i, nil +} + +func (i InternalBridgeValidator) ValidateBasic() error { + if i.Power == 0 { + return sdkerrors.Wrap(ErrEmpty, "power") + } + return nil +} + +func (i InternalBridgeValidator) ToExternal() BridgeValidator { + return BridgeValidator{ + Power: i.Power, + EthereumAddress: i.EthereumAddress.Hex(), + } +} + +// InternalBridgeValidators is the sorted set of validator data for Ethereum bridge MultiSig set. +type InternalBridgeValidators []*InternalBridgeValidator + +func (ibv InternalBridgeValidators) ToExternal() BridgeValidators { + bridgeValidators := make([]BridgeValidator, len(ibv)) + for b := range bridgeValidators { + bridgeValidators[b] = ibv[b].ToExternal() + } + + return BridgeValidators(bridgeValidators) +} + +// Sort sorts the validators by power. +func (ibv InternalBridgeValidators) Sort() { + sort.Slice(ibv, func(i, j int) bool { + if ibv[i].Power == ibv[j].Power { + // Secondary sort on eth address in case powers are equal + return EthAddrLessThan(ibv[i].EthereumAddress, ibv[j].EthereumAddress) + } + return ibv[i].Power > ibv[j].Power + }) +} + +// EthAddrLessThan migrates the Ethereum address less than function. +func EthAddrLessThan(e common.Address, o common.Address) bool { + return bytes.Compare([]byte(e.Hex())[:], []byte(o.Hex())[:]) == -1 +} + +// PowerDiff returns the difference in power between two bridge validator sets +// note this is Gravity bridge power *not* Cosmos voting power. Cosmos voting +// power is based on the absolute number of tokens in the staking pool at any given +// time Gravity bridge power is normalized using the equation. +// +// validators cosmos voting power / total cosmos voting power in this block = gravity bridge power / u32_max +// +// As an example if someone has 52% of the Cosmos voting power when a validator set is created their Gravity +// bridge voting power is u32_max * .52 +// +// Normalized voting power dramatically reduces how often we have to produce new validator set updates. For example +// if the total on chain voting power increases by 1% due to inflation, we shouldn't have to generate a new validator +// set, after all the validators retained their relative percentages during inflation and normalized Gravity bridge power +// shows no difference. +func (ibv InternalBridgeValidators) PowerDiff(c InternalBridgeValidators) float64 { + powers := map[string]int64{} + // loop over ibv and initialize the map with their powers + for _, bv := range ibv { + powers[bv.EthereumAddress.Hex()] = int64(bv.Power) + } + + // subtract c powers from powers in the map, initializing + // uninitialized keys with negative numbers + for _, bv := range c { + if val, ok := powers[bv.EthereumAddress.Hex()]; ok { + powers[bv.EthereumAddress.Hex()] = val - int64(bv.Power) + } else { + powers[bv.EthereumAddress.Hex()] = -int64(bv.Power) + } + } + + var delta float64 + for _, v := range powers { + // NOTE: we care about the absolute value of the changes + delta += math.Abs(float64(v)) + } + + return math.Abs(delta / float64(math.MaxUint32)) +} + +// TotalPower returns the total power in the bridge validator set. +func (ibv InternalBridgeValidators) TotalPower() (out uint64) { + for _, v := range ibv { + out += v.Power + } + return +} + +// HasDuplicates returns true if there are duplicates in the set. +func (ibv InternalBridgeValidators) HasDuplicates() bool { + m := make(map[string]struct{}, len(ibv)) + // creates a hashmap then ensures that the hashmap and the array + // have the same length, this acts as an O(n) duplicates check + for i := range ibv { + m[ibv[i].EthereumAddress.Hex()] = struct{}{} + } + return len(m) != len(ibv) +} + +// GetPowers returns only the power values for all members. +func (ibv InternalBridgeValidators) GetPowers() []uint64 { + r := make([]uint64, len(ibv)) + for i := range ibv { + r[i] = ibv[i].Power + } + return r +} + +// ValidateBasic performs stateless checks. +func (ibv InternalBridgeValidators) ValidateBasic() error { + if len(ibv) == 0 { + return ErrEmpty + } + for i := range ibv { + if err := ibv[i].ValidateBasic(); err != nil { + return sdkerrors.Wrapf(err, "member %d", i) + } + } + if ibv.HasDuplicates() { + return sdkerrors.Wrap(ErrDuplicate, "addresses") + } + return nil +} diff --git a/x/qgb/types/valset.go b/x/qgb/types/valset.go new file mode 100644 index 0000000000..eabebc5bb7 --- /dev/null +++ b/x/qgb/types/valset.go @@ -0,0 +1,90 @@ +package types + +import ( + "fmt" + "math/big" + + wrapper "github.com/celestiaorg/quantum-gravity-bridge/wrappers/QuantumGravityBridge.sol" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + ethcmn "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +var _ AttestationRequestI = &Valset{} + +// NewValset returns a new valset. +func NewValset(nonce, height uint64, members InternalBridgeValidators) (*Valset, error) { + if err := members.ValidateBasic(); err != nil { + return nil, sdkerrors.Wrap(err, "invalid members") + } + members.Sort() + mem := make([]BridgeValidator, 0) + for _, val := range members { + mem = append(mem, val.ToExternal()) + } + vs := Valset{Nonce: nonce, Members: mem, Height: height} + return &vs, nil +} + +// SignBytes produces the bytes that celestia validators are required to sign +// over when the validator set changes. +func (v *Valset) SignBytes(bridgeID ethcmn.Hash) (ethcmn.Hash, error) { + vsHash, err := v.Hash() + if err != nil { + return ethcmn.Hash{}, err + } + + // the word 'checkpoint' needs to be the same as the 'name' above in the checkpointAbiJson + // but other than that it's a constant that has no impact on the output. This is because + // it gets encoded as a function name which we must then discard. + bytes, err := InternalQGBabi.Pack( + "domainSeparateValidatorSetHash", + bridgeID, + VsDomainSeparator, + big.NewInt(int64(v.Nonce)), + big.NewInt(int64(v.TwoThirdsThreshold())), + vsHash, + ) + // this should never happen outside of test since any case that could crash on encoding + // should be filtered above. + if err != nil { + panic(fmt.Sprintf("Error packing checkpoint! %s/n", err)) + } + + hash := crypto.Keccak256Hash(bytes[4:]) + return hash, nil +} + +// Hash mimics the 'computeValsetHash' function used by the qgb contracts by using +// a Valset to compute the hash of the abi encoded validator set. +func (v *Valset) Hash() (ethcmn.Hash, error) { + ethVals := make([]wrapper.Validator, len(v.Members)) + for i, val := range v.Members { + ethVals[i] = wrapper.Validator{ + Addr: ethcmn.HexToAddress(val.EthereumAddress), + Power: big.NewInt(int64(val.Power)), + } + } + + encodedVals, err := InternalQGBabi.Pack("computeValidatorSetHash", ethVals) + if err != nil { + return ethcmn.Hash{}, err + } + + return crypto.Keccak256Hash(encodedVals[4:]), nil +} + +func (v *Valset) TwoThirdsThreshold() uint64 { + totalPower := uint64(0) + for _, member := range v.Members { + totalPower += member.Power + } + + // todo: fix to be more precise + oneThird := (totalPower / 3) + 1 // +1 to round up + return 2 * oneThird +} + +func (v Valset) Type() AttestationType { + return ValsetRequestType +} diff --git a/x/qgb/types/valset_confirm.go b/x/qgb/types/valset_confirm.go new file mode 100644 index 0000000000..ccee18752c --- /dev/null +++ b/x/qgb/types/valset_confirm.go @@ -0,0 +1,38 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/common" +) + +var _ sdk.Msg = &MsgValsetConfirm{} + +// GetSigners defines whose signature is required. +func (msg *MsgValsetConfirm) GetSigners() []sdk.AccAddress { + // TODO: figure out how to convert between AccAddress and ValAddress properly + acc, err := sdk.AccAddressFromBech32(msg.Orchestrator) + if err != nil { + panic(err) + } + + return []sdk.AccAddress{acc} +} + +// ValidateBasic performs stateless checks. +func (msg *MsgValsetConfirm) ValidateBasic() (err error) { + if _, err = sdk.AccAddressFromBech32(msg.Orchestrator); err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Orchestrator) + } + if !common.IsHexAddress(msg.EthAddress) { + return sdkerrors.Wrap(stakingtypes.ErrEthAddressNotHex, "ethereum address") + } + return nil +} + +// Type should return the action. +func (msg *MsgValsetConfirm) Type() string { return "/qgb.MsgValsetConfirm" } + +// Route fullfills the sdk.Msg interface. +func (msg *MsgValsetConfirm) Route() string { return RouterKey } diff --git a/x/qgb/types/valsetconfirm.go b/x/qgb/types/valsetconfirm.go deleted file mode 100644 index 526e5e29ed..0000000000 --- a/x/qgb/types/valsetconfirm.go +++ /dev/null @@ -1,21 +0,0 @@ -package types - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// GetSigners defines whose signature is required -func (msg *MsgValsetConfirm) GetSigners() []sdk.AccAddress { - // TODO: figure out how to convert between AccAddress and ValAddress properly - acc, err := sdk.AccAddressFromBech32(msg.Orchestrator) - if err != nil { - panic(err) - } - return []sdk.AccAddress{acc} -} - -// ValidateBasic -func (msg *MsgValsetConfirm) ValidateBasic() error { - // TODO - return nil -}