Skip to content

Commit

Permalink
feat: implement wrapper around CometBFT RPC client (#1)
Browse files Browse the repository at this point in the history
* chore: update .gitignore

Update .gitignore to include the vendor/ directory and all subdirectories. It will likely be desirable to check this directory into version control but for now I'm excluding these files for simplicity.

* chore: update README.md

* chore: add basic Makefile

* chore: add .golangci.yml config file

* feat: implement RPC client wrapper around CometBFT's RPC client

Implement a Client type that serves as a wrapper around the CometBFT RPC client. Currently only supports the most recent version of CometBFT but will include support for legacy versions of CometBFT so that we can handle API breaking changes that are introduced upstream.

* chore: update .gitignore

* chore: checkin the vendor/ directory

* feat: bring in slimmed down cometbft client

* chore: check in files missed in previous commit

* remove cometbft dep

* Fix validator updates unmarshal

* chore: update deps

* feat: handle decoding of events from BlockResults & embed the rpc client in our wrapper

Internally try to handle the decoding of events from the BlockResults RPC call internally so that downstream users don't have to consider this detail. We also embed the cometbft rpc client in our wrapper to avoid unnecessary indirection.

* feat: define response types to be used by client wrapper

* refactor: encapsulate comet rpc client & implement methods to invoke rpc calls from wrapper

* test: update test cases

* chore: implement IsOK method for checking query response code

* chore: add Make target for running unit tests

* fix: change json key to camelcase from snake case for proof ops

* fix: allocate memory for slice correctly

* feat: implement missing RPC calls as methods on Client

---------

Co-authored-by: Andrew Gouin <[email protected]>
  • Loading branch information
jtieri and agouin authored Jan 24, 2024
1 parent 152823a commit c8fa02c
Show file tree
Hide file tree
Showing 155 changed files with 19,572 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*.out

# Dependency directories (remove the comment below to include it)
# vendor/
vendor/*

# Go workspace file
go.work
17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
default: help

.PHONY: help
help: ## Print this help message
@echo "Available make commands:"; grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

.PHONY: lint
lint: ## Run golangci-lint
golangci-lint run --out-format=tab

.PHONY: lint-fix
lint-fix: ## Run golangci-lint with the --fix flag to fix linter errors
golangci-lint run --fix --out-format=tab --issues-exit-code=0

.PHONY: test
test: ## Run the Go unit tests
go test -race -v ./...
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
# cometbft-client
# cometbft-client

Basic wrapper around the CometBFT RPC client. Useful for maintaing support for both current and
legacy versions of CometBFT.
104 changes: 104 additions & 0 deletions abci/types/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package types

import "github.com/strangelove-ventures/cometbft-client/proto/tendermint/crypto"

const (
CodeTypeOK uint32 = 0
)

// ValidatorUpdates is a list of validators that implements the Sort interface
type ValidatorUpdates []ValidatorUpdate

type ValidatorUpdate struct {
PubKey crypto.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"`
Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"`
}

type ExecTxResult struct {
Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"`
GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"`
Events []Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"`
Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"`
}

// IsOK returns true if Code is OK.
func (r ExecTxResult) IsOK() bool {
return r.Code == CodeTypeOK
}

// IsErr returns true if Code is something other than OK.
func (r ExecTxResult) IsErr() bool {
return r.Code != CodeTypeOK
}

// -----------------------------------------------
// construct Result data

// Event allows application developers to attach additional information to
// ResponseFinalizeBlock and ResponseCheckTx.
// Later, transactions may be queried using these events.
type Event struct {
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
Attributes []EventAttribute `protobuf:"bytes,2,rep,name=attributes,proto3" json:"attributes,omitempty"`
}

// EventAttribute is a single key-value pair, associated with an event.
type EventAttribute struct {
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
Index bool `protobuf:"varint,3,opt,name=index,proto3" json:"index,omitempty"`
}

type ResponseInfo struct {
Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
AppVersion uint64 `protobuf:"varint,3,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"`
LastBlockHeight int64 `protobuf:"varint,4,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"`
LastBlockAppHash []byte `protobuf:"bytes,5,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"`
}

type ResponseQuery struct {
Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
// bytes data = 2; // use "value" instead.
Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
Index int64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"`
Key []byte `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"`
Value []byte `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"`
ProofOps *ProofOps `protobuf:"bytes,8,opt,name=proof_ops,json=proofOps,proto3" json:"proofOps,omitempty"`
Height int64 `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"`
Codespace string `protobuf:"bytes,10,opt,name=codespace,proto3" json:"codespace,omitempty"`
}

func (r *ResponseQuery) IsOK() bool {
return r.Code == CodeTypeOK
}

// ProofOps is Merkle proof defined by the list of ProofOps
type ProofOps struct {
Ops []ProofOp `protobuf:"bytes,1,rep,name=ops,proto3" json:"ops"`
}

// ProofOp defines an operation used for calculating Merkle root
// The data could be arbitrary format, providing nessecary data
// for example neighbouring node hash
type ProofOp struct {
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
}

type ResponseCheckTx struct {
Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"`
GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"`
Events []Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"`
Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"`
}
Loading

0 comments on commit c8fa02c

Please sign in to comment.