informalsystems / CometMock

Drop-in replacement for CometBFT in end-to-end tests
Apache License 2.0
26 stars 2 forks source link

CometMock

CometMock is a mock implementation of CometBFT. It is meant to be used as a drop-in replacement for CometBFT in end-to-end tests. Some of the reasons to use CometMock instead of CometBFT are:

On a technical level, CometMock communicates with applications via ABCI through GRPC or TSP (Tendermint Socket Protocol) calls. It calls BeginBlock, DeliverTx, EndBlock and Commit like CometBFT does during normal execution.

Currently, CometMock maintains releases compatible with CometBFT v0.38, v0.37 and v0.34, see branches v0.34.x, v0.37.x and v0.38.x. It offers many of the RPC endpoints offered by Comet (see https://docs.cometbft.com/v0.34/rpc/, https://docs.cometbft.com/v0.37/rpc/ and https://docs.cometbft.com/v0.38/rpc/ for the respective version of the interface), in particular it supports the subset used by Gorelayer (https://github.com/cosmos/relayer/). See the endpoints offered here: https://github.com/informalsystems/CometMock/cometmock/rpc_server/routes.go#L30C2-L53

Installation

Run go install ./cometmock, then you can run cometmock to see usage information. CometMock was tested with go version go1.20.3 darwin/arm64.

How to use

To run CometMock, start your (cosmos-sdk) application instances with the flags --with-tendermint=false, --transport=grpc. After the applications started, start CometMock like this

cometmock [--block-time=value] [--auto-tx=<value>] [--block-production-interval=<value>] [--starting-timestamp=<value>] [--starting-timestamp-from-genesis=<value>] {app_address1,app_address2,...} {genesis_file} {cometmock_listen_address} {home_folder1,home_folder2,...} {connection_mode}

where:

When calling the cosmos sdk cli, use as node address the cometmock_listen_address, e.g. simd q bank total --node {cometmock_listen_address}.

CometMock specific RPC endpoints

Here is a quick explanation and example usage of each of the endpoints that are custom to CometMock

Advance enough blocks to get the valdator downtime-slashed

curl -H 'Content-Type: application/json' -H 'Accept:application/json' --data '{"jsonrpc":"2.0","method":"advance_blocks","params":{"num_blocks": "20"},"id":1}' 127.0.0.1:22331

Make the validator sign again

curl -H 'Content-Type: application/json' -H 'Accept:application/json' --data '{"jsonrpc":"2.0","method":"set_signing_status","params":{"private_key_address": "'"$PRIV_VALIDATOR_ADDRESS"'", "status": "up"},"id":1}' 127.0.0.1:22331


* `advance_time(duration_in_seconds)`: Advances the local time of the blockchain by `duration_in_seconds` seconds. Under the hood, this is done by giving the application timestamps offset by the sum of time advancements that happened so far.
When you test with multiple chains, be aware that you should advance chains at the same time, otherwise e.g. IBC will break due to large differences in the times of the different chains.
This is constant time no matter the duration you advance by.
Example usage:

curl -H 'Content-Type: application/json' -H 'Accept:application/json' --data '{"jsonrpc":"2.0","method":"advance_time","params":{"duration_in_seconds": "36000000"},"id":1}' 127.0.0.1:22331



* `cause_double_sign(private_key_address)`: Causes the validator with the given private key to double sign. This is done by signing two blocks with the same height. This will produce DuplicateVoteEvidence and propagate it to the app via ABCI.

* `cause_light_client_attack(private_key_address, misbehaviour_type)`: Will produce LightClientAttackEvidence for the validator with the given private key. This will produce evidence in one of three different ways. Misbehaviour type can be:
* Equivocation: The evidence has a conflicting block that has the same height, but a non-deterministic field is different, e.g. time.
* Lunatic: The evidence has a conflicting block that differs in the app hash.
* Amnesia: The evidence has a conflicting block that is the same as the original block.

## Limitations

### Not all CometBFT RPC endpoints are implemented
Out of a desire to avoid unnecessary bloat, not all CometBFT RPC endpoints from https://docs.cometbft.com/v0.34/rpc/ are implemented.
If you want to use CometMock but an RPC endpoint you rely on isn't present, please create an issue.

### Cosmos SDK GRPC endpoints are not working
Cosmos SDK applications started with `--with-tendermint=false`
do not start their grpc server, see https://github.com/cosmos/cosmos-sdk/issues/16277.
This is a limitation of the Cosmos SDK related to using out-of-process consensus.

### --gas auto is not working
Related, using `--gas auto` calls a cosmos sdk grpc endpoint, so it won't be possible with CometMock.
It is recommended to manually specify a large enough gas amount.

### Hermes does not work with CometMock
In particular, the fact that the cosmos sdk grpc endpoints are incompatible with having
out-of-process consensus prevents CometMock from working with Hermes, since Hermes calls the SDK grpc endpoints.
If you need a relayer with CometMock, the go relayer https://github.com/cosmos/relayer 
is an alternative. The only caveat is that it typically calls the gas simulation, which doesn't work with CometMock.
Here is a fork of the gorelayer that removes the gas simulation in favor of a fixed value https://github.com/p-offtermatt/relayer/tree/v2.3.0-no-gas-sim.
see this commit for the changes https://github.com/p-offtermatt/relayer/commit/39bc4b82acf1f95b9a8d40a281c3f90178d72d00

## Disclaimer

CometMock is under heavy development and work-in-progress.
Use at your own risk. In the current state, testing with CometMock cannot fully replace proper end-to-end tests
with CometBFT.

## License Information

Copyright © 2023 Informal Systems Inc. and CometMock authors.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use the files in this repository except in compliance with the License. You may obtain a copy of the License at

```https://www.apache.org/licenses/LICENSE-2.0```

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.