Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(zetaclient): add more function and package documentation #2321

Merged
merged 18 commits into from
Jun 26, 2024
Merged
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -98,6 +98,10 @@
* [2335](https://github.com/zeta-chain/node/pull/2335) - ci: updated the artillery report to publish to artillery cloud
* [2377](https://github.com/zeta-chain/node/pull/2377) - ci: adjusted sast-linters.yml to not scan itself, nor alert on removal of nosec.

### Documentation

* [2321](https://github.com/zeta-chain/node/pull/2321) - improve documentation for ZetaClient functions and packages

## v17.0.0

### Fixes
8 changes: 8 additions & 0 deletions zetaclient/authz/authz_signer.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Package authz provides a signer object for transactions using grants
lumtis marked this conversation as resolved.
Show resolved Hide resolved
// grants are used to allow a hotkey to sign transactions on behalf of the observers
package authz

import (
@@ -7,18 +9,22 @@ import (
crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types"
)

// Signer represents a signer for a grantee key
type Signer struct {
KeyType authz.KeyType
GranterAddress string
GranteeAddress sdk.AccAddress
}

// String returns a string representation of a Signer
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (a Signer) String() string {
return a.KeyType.String() + " " + a.GranterAddress + " " + a.GranteeAddress.String()
}

// signers is a map of all the signers for the different tx types
var signers map[string]Signer

// init initializes the signers map with all the crosschain tx types using the ZetaClientGranteeKey
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func init() {
signersList := make(map[string]Signer)
for _, tx := range crosschaintypes.GetAllAuthzZetaclientTxTypes() {
@@ -27,6 +33,7 @@ func init() {
signers = signersList
}

// SetupAuthZSignerList sets the granter and grantee for all the signers
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func SetupAuthZSignerList(granter string, grantee sdk.AccAddress) {
for k, v := range signers {
v.GranterAddress = granter
@@ -35,6 +42,7 @@ func SetupAuthZSignerList(granter string, grantee sdk.AccAddress) {
}
}

// GetSigner returns the signer for a given msgURL
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func GetSigner(msgURL string) Signer {
return signers[msgURL]
}
2 changes: 2 additions & 0 deletions zetaclient/authz/authz_signer_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
package authz_test

// NOTE: test file currently created empty to add the package in the test coverage scope
9 changes: 9 additions & 0 deletions zetaclient/chains/bitcoin/observer/inbound.go
Original file line number Diff line number Diff line change
@@ -26,6 +26,8 @@ import (
)

// WatchInbound watches Bitcoin chain for inbounds on a ticker
// It starts a ticker and run ObserveInbound
// TODO(revamp): move all ticker related methods in the same file
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) WatchInbound() {
ticker, err := types.NewDynamicTicker("Bitcoin_WatchInbound", ob.GetChainParams().InboundTicker)
if err != nil {
@@ -37,6 +39,7 @@ func (ob *Observer) WatchInbound() {
ob.logger.Inbound.Info().Msgf("WatchInbound started for chain %d", ob.Chain().ChainId)
sampledLogger := ob.logger.Inbound.Sample(&zerolog.BasicSampler{N: 10})

// ticker loop
for {
select {
case <-ticker.C():
@@ -58,6 +61,7 @@ func (ob *Observer) WatchInbound() {
}

// ObserveInbound observes the Bitcoin chain for inbounds and post votes to zetacore
// TODO(revamp): simplify this function into smaller functions
func (ob *Observer) ObserveInbound() error {
// get and update latest block height
cnt, err := ob.btcClient.GetBlockCount()
@@ -171,6 +175,7 @@ func (ob *Observer) ObserveInbound() error {
}

// WatchInboundTracker watches zetacore for bitcoin inbound trackers
// TODO(revamp): move all ticker related methods in the same file
func (ob *Observer) WatchInboundTracker() {
ticker, err := types.NewDynamicTicker("Bitcoin_WatchInboundTracker", ob.GetChainParams().InboundTicker)
if err != nil {
@@ -200,6 +205,7 @@ func (ob *Observer) WatchInboundTracker() {
}

// ProcessInboundTrackers processes inbound trackers
// TODO(revamp): move inbound tracker logic in a specific file
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) ProcessInboundTrackers() error {
trackers, err := ob.ZetacoreClient().GetInboundTrackersForChain(ob.Chain().ChainId)
if err != nil {
@@ -328,6 +334,7 @@ func FilterAndParseIncomingTx(
return inbounds, nil
}

// GetInboundVoteMessageFromBtcEvent converts a BTCInboundEvent to a MsgVoteInbound to enable voting on the inbound on zetacore
func (ob *Observer) GetInboundVoteMessageFromBtcEvent(inbound *BTCInboundEvent) *crosschaintypes.MsgVoteInbound {
ob.logger.Inbound.Debug().Msgf("Processing inbound: %s", inbound.TxHash)
amount := big.NewFloat(inbound.Value)
@@ -360,6 +367,7 @@ func (ob *Observer) GetInboundVoteMessageFromBtcEvent(inbound *BTCInboundEvent)
}

// DoesInboundContainsRestrictedAddress returns true if the inbound contains restricted addresses
// TODO(revamp): move all compliance related functions in a specific file
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) DoesInboundContainsRestrictedAddress(inTx *BTCInboundEvent) bool {
receiver := ""
parsedAddress, _, err := chains.ParseAddressAndData(hex.EncodeToString(inTx.MemoBytes))
@@ -376,6 +384,7 @@ func (ob *Observer) DoesInboundContainsRestrictedAddress(inTx *BTCInboundEvent)

// GetBtcEvent either returns a valid BTCInboundEvent or nil
// Note: the caller should retry the tx on error (e.g., GetSenderAddressByVin failed)
// TODO(revamp): simplify this function
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func GetBtcEvent(
rpcClient interfaces.BTCRPCClient,
tx btcjson.TxRawResult,
16 changes: 14 additions & 2 deletions zetaclient/chains/bitcoin/observer/observer.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package observer implements the Bitcoin chain observer
package observer

import (
@@ -54,6 +55,7 @@ type Logger struct {
}

// BTCInboundEvent represents an incoming transaction event
// TODO(revamp): Move to inbound
lumtis marked this conversation as resolved.
Show resolved Hide resolved
type BTCInboundEvent struct {
// FromAddress is the first input address
FromAddress string
@@ -69,7 +71,7 @@ type BTCInboundEvent struct {
TxHash string
}

// BTCOutboundEvent contains bitcoin block and the header
// BTCBlockNHeader contains bitcoin block and the header
type BTCBlockNHeader struct {
Header *wire.BlockHeader
Block *btcjson.GetBlockVerboseTxResult
@@ -190,7 +192,7 @@ func (ob *Observer) GetChainParams() observertypes.ChainParams {
return ob.ChainParams()
}

// Start starts the Go routine to observe the Bitcoin chain
// Start starts the Go routine processes to observe the Bitcoin chain
func (ob *Observer) Start() {
ob.Logger().Chain.Info().Msgf("observer is starting for chain %d", ob.Chain().ChainId)

@@ -214,6 +216,8 @@ func (ob *Observer) Start() {
}

// WatchRPCStatus watches the RPC status of the Bitcoin chain
// TODO(revamp): move ticker related functions to a specific file
// TODO(revamp): move inner logic in a separate function
func (ob *Observer) WatchRPCStatus() {
ob.logger.Chain.Info().Msgf("RPCStatus is starting")
ticker := time.NewTicker(60 * time.Second)
@@ -297,6 +301,8 @@ func (ob *Observer) ConfirmationsThreshold(amount *big.Int) int64 {
}

// WatchGasPrice watches Bitcoin chain for gas rate and post to zetacore
// TODO(revamp): move ticker related functions to a specific file
// TODO(revamp): move inner logic in a separate function
func (ob *Observer) WatchGasPrice() {
// report gas price right away as the ticker takes time to kick in
err := ob.PostGasPrice()
@@ -333,6 +339,7 @@ func (ob *Observer) WatchGasPrice() {
}

// PostGasPrice posts gas price to zetacore
// TODO(revamp): move to gas price file
func (ob *Observer) PostGasPrice() error {
// hardcode gas price here since this RPC is not available on regtest
if chains.IsBitcoinRegnet(ob.Chain().ChainId) {
@@ -379,6 +386,7 @@ func (ob *Observer) PostGasPrice() error {
}

// GetSenderAddressByVin get the sender address from the previous transaction
// TODO(revamp): move in upper package to separate file (e.g., rpc.go)
func GetSenderAddressByVin(rpcClient interfaces.BTCRPCClient, vin btcjson.Vin, net *chaincfg.Params) (string, error) {
// query previous raw transaction by txid
// GetTransaction requires reconfiguring the bitcoin node (txindex=1), so we use GetRawTransaction instead
@@ -421,6 +429,7 @@ func GetSenderAddressByVin(rpcClient interfaces.BTCRPCClient, vin btcjson.Vin, n
}

// WatchUTXOs watches bitcoin chain for UTXOs owned by the TSS address
// TODO(revamp): move ticker related functions to a specific file
func (ob *Observer) WatchUTXOs() {
ticker, err := clienttypes.NewDynamicTicker("Bitcoin_WatchUTXOs", ob.GetChainParams().WatchUtxoTicker)
if err != nil {
@@ -448,6 +457,7 @@ func (ob *Observer) WatchUTXOs() {
}

// FetchUTXOs fetches TSS-owned UTXOs from the Bitcoin node
// TODO(revamp): move to UTXO file
func (ob *Observer) FetchUTXOs() error {
defer func() {
if err := recover(); err != nil {
@@ -511,6 +521,7 @@ func (ob *Observer) FetchUTXOs() error {
}

// SaveBroadcastedTx saves successfully broadcasted transaction
// TODO(revamp): move to db file
func (ob *Observer) SaveBroadcastedTx(txHash string, nonce uint64) {
outboundID := ob.GetTxID(nonce)
ob.Mu().Lock()
@@ -641,6 +652,7 @@ func (ob *Observer) isTssTransaction(txid string) bool {
}

// postBlockHeader posts block header to zetacore
// TODO(revamp): move to block header file
func (ob *Observer) postBlockHeader(tip int64) error {
ob.logger.Inbound.Info().Msgf("postBlockHeader: tip %d", tip)
bn := tip
8 changes: 8 additions & 0 deletions zetaclient/chains/bitcoin/observer/outbound.go
Original file line number Diff line number Diff line change
@@ -27,6 +27,8 @@ func (ob *Observer) GetTxID(nonce uint64) string {
}

// WatchOutbound watches Bitcoin chain for outgoing txs status
// TODO(revamp): move ticker functions to a specific file
// TODO(revamp): move into a separate package
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) WatchOutbound() {
ticker, err := types.NewDynamicTicker("Bitcoin_WatchOutbound", ob.GetChainParams().OutboundTicker)
if err != nil {
@@ -111,6 +113,7 @@ func (ob *Observer) WatchOutbound() {
}

// IsOutboundProcessed returns isIncluded(or inMempool), isConfirmed, Error
// TODO(revamp): rename as it vote the outbound and doesn't only check if outbound is processed
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) IsOutboundProcessed(cctx *crosschaintypes.CrossChainTx, logger zerolog.Logger) (bool, bool, error) {
params := *cctx.GetCurrentOutboundParam()
sendHash := cctx.Index
@@ -213,6 +216,8 @@ func (ob *Observer) IsOutboundProcessed(cctx *crosschaintypes.CrossChainTx, logg
// - the total value of the selected UTXOs.
// - the number of consolidated UTXOs.
// - the total value of the consolidated UTXOs.
//
// TODO(revamp): move to utxo file
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) SelectUTXOs(
amount float64,
utxosToSpend uint16,
@@ -329,6 +334,8 @@ func (ob *Observer) refreshPendingNonce() {
}
}

// getOutboundIDByNonce gets the outbound ID from the nonce of the outbound transaction
// test is true for unit test only
func (ob *Observer) getOutboundIDByNonce(nonce uint64, test bool) (string, error) {
// There are 2 types of txids an observer can trust
// 1. The ones had been verified and saved by observer self.
@@ -363,6 +370,7 @@ func (ob *Observer) getOutboundIDByNonce(nonce uint64, test bool) (string, error
return "", fmt.Errorf("getOutboundIDByNonce: cannot find outbound txid for nonce %d", nonce)
}

// findNonceMarkUTXO finds the nonce-mark UTXO in the list of UTXOs.
func (ob *Observer) findNonceMarkUTXO(nonce uint64, txid string) (int, error) {
tssAddress := ob.TSS().BTCAddressWitnessPubkeyHash().EncodeAddress()
amount := chains.NonceMarkAmount(nonce)
5 changes: 5 additions & 0 deletions zetaclient/chains/bitcoin/signer/signer.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package signer implements the ChainSigner interface for BTC
package signer

import (
@@ -168,6 +169,7 @@ func (signer *Signer) AddWithdrawTxOutputs(
}

// SignWithdrawTx receives utxos sorted by value, amount in BTC, feeRate in BTC per Kb
// TODO(revamp): simplify the function
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (signer *Signer) SignWithdrawTx(
to btcutil.Address,
amount float64,
@@ -291,6 +293,7 @@ func (signer *Signer) SignWithdrawTx(
return tx, nil
}

// Broadcast sends the signed transaction to the network
func (signer *Signer) Broadcast(signedTx *wire.MsgTx) error {
fmt.Printf("BTCSigner: Broadcasting: %s\n", signedTx.TxHash().String())

@@ -311,6 +314,8 @@ func (signer *Signer) Broadcast(signedTx *wire.MsgTx) error {
return nil
}

// TryProcessOutbound signs and broadcasts a BTC transaction from a new outbound
lumtis marked this conversation as resolved.
Show resolved Hide resolved
// TODO(revamp): simplify the function
func (signer *Signer) TryProcessOutbound(
cctx *types.CrossChainTx,
outboundProcessor *outboundprocessor.Processor,
5 changes: 5 additions & 0 deletions zetaclient/chains/bitcoin/utils.go
Original file line number Diff line number Diff line change
@@ -8,6 +8,9 @@ import (
"github.com/pkg/errors"
)

// TODO(revamp): Remove utils.go and move the functions to the appropriate files
lumtis marked this conversation as resolved.
Show resolved Hide resolved

// PrettyPrintStruct returns a pretty-printed string representation of a struct
func PrettyPrintStruct(val interface{}) (string, error) {
prettyStruct, err := json.MarshalIndent(
val,
@@ -20,6 +23,7 @@ func PrettyPrintStruct(val interface{}) (string, error) {
return string(prettyStruct), nil
}

// GetSatoshis converts a bitcoin amount to satoshis
func GetSatoshis(btc float64) (int64, error) {
// The amount is only considered invalid if it cannot be represented
// as an integer type. This may happen if f is NaN or +-Infinity.
@@ -39,6 +43,7 @@ func GetSatoshis(btc float64) (int64, error) {
return round(btc * btcutil.SatoshiPerBitcoin), nil
}

// round rounds a float64 to the nearest integer
func round(f float64) int64 {
if f < 0 {
// #nosec G701 always in range
4 changes: 4 additions & 0 deletions zetaclient/chains/evm/observer/inbound.go
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ import (
)

// WatchInbound watches evm chain for incoming txs and post votes to zetacore
// TODO(revamp): move ticker function to a separate file
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) WatchInbound() {
ticker, err := clienttypes.NewDynamicTicker(
fmt.Sprintf("EVM_WatchInbound_%d", ob.Chain().ChainId),
@@ -70,6 +71,7 @@ func (ob *Observer) WatchInbound() {

// WatchInboundTracker gets a list of Inbound tracker suggestions from zeta-core at each tick and tries to check if the in-tx was confirmed.
// If it was, it tries to broadcast the confirmation vote. If this zeta client has previously broadcast the vote, the tx would be rejected
// TODO(revamp): move inbound tracker function to a separate file
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) WatchInboundTracker() {
ticker, err := clienttypes.NewDynamicTicker(
fmt.Sprintf("EVM_WatchInboundTracker_%d", ob.Chain().ChainId),
@@ -101,6 +103,7 @@ func (ob *Observer) WatchInboundTracker() {
}

// ProcessInboundTrackers processes inbound trackers from zetacore
// TODO(revamp): move inbound tracker function to a separate file
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) ProcessInboundTrackers() error {
trackers, err := ob.ZetacoreClient().GetInboundTrackersForChain(ob.Chain().ChainId)
if err != nil {
@@ -152,6 +155,7 @@ func (ob *Observer) ProcessInboundTrackers() error {
return nil
}

// ObserveInbound observes the evm chain for inbounds and posts votes to zetacore
lumtis marked this conversation as resolved.
Show resolved Hide resolved
lumtis marked this conversation as resolved.
Show resolved Hide resolved
func (ob *Observer) ObserveInbound(sampledLogger zerolog.Logger) error {
// get and update latest block height
blockNumber, err := ob.evmClient.BlockNumber(context.Background())
Loading