Skip to content

Commit 0d79cfb

Browse files
fbackingpinXD
andauthored
refactor: add VoteOnBallot function (#2464)
* refactor: add FindBallotAndFinalize function Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> * refactor blame and block header Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> * refactor: move VoteOnBallot to utils.go Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> * refactor: run make generate Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> * remove wontfix issues Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> * refactor: add changelog Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> * refactor: remove sprintf Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> * refactor: add VoteOnBallot testing suite Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> * Update x/observer/keeper/voting_test.go Co-authored-by: Tanmay <[email protected]> * refactor: replace index with sample.ZetaIndex(t) Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> * refactored errors returning from votes Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> --------- Signed-off-by: Francisco de Borja Aranda Castillejo <[email protected]> Co-authored-by: Tanmay <[email protected]>
1 parent a076710 commit 0d79cfb

12 files changed

+444
-166
lines changed

changelog.md

+7-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* [2339](https://github.com/zeta-chain/node/pull/2339) - add binaries related question to syncing issue form
3131
* [2366](https://github.com/zeta-chain/node/pull/2366) - add migration script for adding authorizations table
3232
* [2372](https://github.com/zeta-chain/node/pull/2372) - add queries for tss fund migration info
33-
* [2416g](https://github.com/zeta-chain/node/pull/2416) - add Solana chain information
33+
* [2416](https://github.com/zeta-chain/node/pull/2416) - add Solana chain information
3434

3535
### Refactor
3636

@@ -59,6 +59,7 @@
5959
* [2380](https://github.com/zeta-chain/node/pull/2380) - use `ChainInfo` in `authority` to allow dynamically support new chains
6060
* [2395](https://github.com/zeta-chain/node/pull/2395) - converge AppContext with ZetaCoreContext in zetaclient
6161
* [2428](https://github.com/zeta-chain/node/pull/2428) - propagate context across codebase & refactor zetacore client
62+
* [2464](https://github.com/zeta-chain/node/pull/2464) - move common voting logic to voting.go and add new function VoteOnBallot
6263

6364
### Tests
6465

@@ -95,6 +96,7 @@
9596
* [2434](https://github.com/zeta-chain/node/pull/2434) - the default database when running `zetacored init` is now pebbledb
9697

9798
### CI
99+
98100
* [2388](https://github.com/zeta-chain/node/pull/2388) - added GitHub attestations of binaries produced in the release workflow.
99101
* [2285](https://github.com/zeta-chain/node/pull/2285) - added nightly EVM performance testing pipeline, modified localnet testing docker image to utilitze debian:bookworm, removed build-jet runners where applicable, removed deprecated/removed upgrade path testing pipeline
100102
* [2268](https://github.com/zeta-chain/node/pull/2268) - updated the publish-release pipeline to utilize the Github Actions Ubuntu 20.04 Runners
@@ -214,7 +216,7 @@
214216
* [1861](https://github.com/zeta-chain/node/pull/1861) - fix `ObserverSlashAmount` invalid read
215217
* [1880](https://github.com/zeta-chain/node/issues/1880) - lower the gas price multiplier for EVM chains
216218
* [1883](https://github.com/zeta-chain/node/issues/1883) - zetaclient should check 'IsSupported' flag to pause/unpause a specific chain
217-
* * [2076](https://github.com/zeta-chain/node/pull/2076) - automatically deposit native zeta to an address if it doesn't exist on ZEVM
219+
* [2076](https://github.com/zeta-chain/node/pull/2076) - automatically deposit native zeta to an address if it doesn't exist on ZEVM
218220
* [1633](https://github.com/zeta-chain/node/issues/1633) - zetaclient should be able to pick up new connector and erc20Custody addresses
219221
* [1944](https://github.com/zeta-chain/node/pull/1944) - fix evm signer unit tests
220222
* [1888](https://github.com/zeta-chain/node/issues/1888) - zetaclient should stop inbound/outbound txs according to cross-chain flags
@@ -237,11 +239,12 @@
237239
## Version: v15.0.0
238240

239241
### Features
242+
240243
* [1912](https://github.com/zeta-chain/node/pull/1912) - add reset chain nonces msg
241244

242245
## Version: v14.0.1
243246

244-
- [1817](https://github.com/zeta-chain/node/pull/1817) - Add migration script to fix pending and chain nonces on testnet
247+
* [1817](https://github.com/zeta-chain/node/pull/1817) - Add migration script to fix pending and chain nonces on testnet
245248

246249
## Version: v13.0.0
247250

@@ -550,4 +553,4 @@ Getting the correct TSS address for Bitcoin now requires proviidng the Bitcoin c
550553
### CI
551554

552555
* [1218](https://github.com/zeta-chain/node/pull/1218) - cross-compile release binaries and simplify PR testings
553-
* [1302](https://github.com/zeta-chain/node/pull/1302) - add mainnet builds to goreleaser
556+
* [1302](https://github.com/zeta-chain/node/pull/1302) - add mainnet builds to goreleaser

x/crosschain/keeper/msg_server_vote_gas_price.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package keeper
22

33
import (
44
"context"
5-
"fmt"
65
"math/big"
76
"sort"
87
"strconv"
@@ -28,7 +27,7 @@ func (k msgServer) VoteGasPrice(
2827

2928
chain, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, msg.ChainId)
3029
if !found {
31-
return nil, cosmoserrors.Wrap(types.ErrUnsupportedChain, fmt.Sprintf("ChainID : %d ", msg.ChainId))
30+
return nil, cosmoserrors.Wrapf(types.ErrUnsupportedChain, "ChainID: %d ", msg.ChainId)
3231
}
3332
if ok := k.zetaObserverKeeper.IsNonTombstonedObserver(ctx, msg.Creator); !ok {
3433
return nil, observertypes.ErrNotObserver

x/crosschain/keeper/msg_server_vote_inbound_tx.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ package keeper
22

33
import (
44
"context"
5-
"fmt"
65

7-
cosmoserrors "cosmossdk.io/errors"
6+
sdkerrors "cosmossdk.io/errors"
87
sdk "github.com/cosmos/cosmos-sdk/types"
98

109
"github.com/zeta-chain/zetacore/x/crosschain/types"
1110
)
1211

12+
const voteInboundID = "Vote Inbound"
13+
1314
// FIXME: use more specific error types & codes
1415

1516
// VoteInbound casts a vote on an inbound transaction observed on a connected chain. If this
@@ -73,22 +74,21 @@ func (k msgServer) VoteInbound(
7374
msg.InboundHash,
7475
)
7576
if err != nil {
76-
return nil, err
77+
return nil, sdkerrors.Wrap(err, voteInboundID)
7778
}
7879

7980
// If it is a new ballot, check if an inbound with the same hash, sender chain and event index has already been finalized
8081
// This may happen if the same inbound is observed twice where msg.Digest gives a different index
8182
// This check prevents double spending
8283
if isNew {
8384
if k.IsFinalizedInbound(tmpCtx, msg.InboundHash, msg.SenderChainId, msg.EventIndex) {
84-
return nil, cosmoserrors.Wrap(
85+
return nil, sdkerrors.Wrapf(
8586
types.ErrObservedTxAlreadyFinalized,
86-
fmt.Sprintf(
87-
"inboundHash:%s, SenderChainID:%d, EventIndex:%d",
88-
msg.InboundHash,
89-
msg.SenderChainId,
90-
msg.EventIndex,
91-
),
87+
"%s, InboundHash:%s, SenderChainID:%d, EventIndex:%d",
88+
voteInboundID,
89+
msg.InboundHash,
90+
msg.SenderChainId,
91+
msg.EventIndex,
9292
)
9393
}
9494
}
@@ -100,7 +100,7 @@ func (k msgServer) VoteInbound(
100100

101101
cctx, err := k.ValidateInbound(ctx, msg, true)
102102
if err != nil {
103-
return nil, err
103+
return nil, sdkerrors.Wrap(err, voteInboundID)
104104
}
105105

106106
// Save the inbound CCTX to the store. This is called irrespective of the status of the CCTX or the outcome of the process function.

x/crosschain/keeper/msg_server_vote_outbound_tx.go

+43-34
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
observerkeeper "github.com/zeta-chain/zetacore/x/observer/keeper"
1515
)
1616

17+
const voteOutboundID = "Vote Outbound"
18+
1719
// VoteOutbound casts a vote on an outbound transaction observed on a connected chain (after
1820
// it has been broadcasted to and finalized on a connected chain). If this is
1921
// the first vote, a new ballot is created. When a threshold of votes is
@@ -61,45 +63,48 @@ func (k msgServer) VoteOutbound(
6163
) (*types.MsgVoteOutboundResponse, error) {
6264
ctx := sdk.UnwrapSDKContext(goCtx)
6365

64-
// Validate the message params to verify it against an existing cctx
66+
// Validate the message params to verify it against an existing CCTX.
6567
cctx, err := k.ValidateOutboundMessage(ctx, *msg)
6668
if err != nil {
67-
return nil, err
69+
return nil, cosmoserrors.Wrap(err, voteOutboundID)
6870
}
69-
// get ballot index
71+
7072
ballotIndex := msg.Digest()
71-
// vote on outbound ballot
7273
isFinalizingVote, isNew, ballot, observationChain, err := k.zetaObserverKeeper.VoteOnOutboundBallot(
7374
ctx,
7475
ballotIndex,
7576
msg.OutboundChain,
7677
msg.Status,
7778
msg.Creator)
7879
if err != nil {
79-
return nil, err
80+
return nil, cosmoserrors.Wrap(err, voteOutboundID)
8081
}
81-
// if the ballot is new, set the index to the CCTX
82+
83+
// If the ballot is new, set the index to the CCTX.
8284
if isNew {
8385
observerkeeper.EmitEventBallotCreated(ctx, ballot, msg.ObservedOutboundHash, observationChain)
8486
}
85-
// if not finalized commit state here
87+
88+
// If not finalized commit state here.
8689
if !isFinalizingVote {
8790
return &types.MsgVoteOutboundResponse{}, nil
8891
}
8992

90-
// if ballot successful, the value received should be the out tx amount
93+
// If ballot is successful, the value received should be the out tx amount.
9194
err = cctx.AddOutbound(ctx, *msg, ballot.BallotStatus)
9295
if err != nil {
93-
return nil, err
96+
return nil, cosmoserrors.Wrap(err, voteOutboundID)
9497
}
95-
// Fund the gas stability pool with the remaining funds
98+
99+
// Fund the gas stability pool with the remaining funds.
96100
k.FundStabilityPool(ctx, &cctx)
97101

98102
err = k.ValidateOutboundObservers(ctx, &cctx, ballot.BallotStatus, msg.ValueReceived.String())
99103
if err != nil {
100104
k.SaveFailedOutbound(ctx, &cctx, err.Error(), ballotIndex)
101105
return &types.MsgVoteOutboundResponse{}, nil
102106
}
107+
103108
k.SaveSuccessfulOutbound(ctx, &cctx, ballotIndex)
104109
return &types.MsgVoteOutboundResponse{}, nil
105110
}
@@ -112,7 +117,7 @@ func (k Keeper) FundStabilityPool(ctx sdk.Context, cctx *types.CrossChainTx) {
112117
// Fund the gas stability pool with the remaining funds
113118
if err := k.FundGasStabilityPoolFromRemainingFees(ctx, *cctx.GetCurrentOutboundParam(), cctx.GetCurrentOutboundParam().ReceiverChainId); err != nil {
114119
ctx.Logger().
115-
Error(fmt.Sprintf("VoteOutbound: CCTX: %s Can't fund the gas stability pool with remaining fees %s", cctx.Index, err.Error()))
120+
Error("%s: CCTX: %s Can't fund the gas stability pool with remaining fees %s", voteOutboundID, cctx.Index, err.Error())
116121
}
117122
}
118123

@@ -136,16 +141,18 @@ func (k Keeper) FundGasStabilityPoolFromRemainingFees(
136141
remainingGas := gasLimit - gasUsed
137142
remainingFees := math.NewUint(remainingGas).Mul(gasPrice).BigInt()
138143

139-
// We fund the stability pool with a portion of the remaining fees
144+
// We fund the stability pool with a portion of the remaining fees.
140145
remainingFees = percentOf(remainingFees, RemainingFeesToStabilityPoolPercent)
141-
// Fund the gas stability pool
146+
147+
// Fund the gas stability pool.
142148
if err := k.fungibleKeeper.FundGasStabilityPool(ctx, chainID, remainingFees); err != nil {
143149
return err
144150
}
145151
} else {
146-
return fmt.Errorf("VoteOutbound: The gas limit %d is less than the gas used %d", gasLimit, gasUsed)
152+
return fmt.Errorf("%s: The gas limit %d is less than the gas used %d", voteOutboundID, gasLimit, gasUsed)
147153
}
148154
}
155+
149156
return nil
150157
}
151158

@@ -167,7 +174,6 @@ SaveFailedOutbound saves a failed outbound transaction.It does the following thi
167174
func (k Keeper) SaveFailedOutbound(ctx sdk.Context, cctx *types.CrossChainTx, errMessage string, ballotIndex string) {
168175
cctx.SetAbort(errMessage)
169176
ctx.Logger().Error(errMessage)
170-
171177
k.SaveOutbound(ctx, cctx, ballotIndex)
172178
}
173179

@@ -195,48 +201,51 @@ func (k Keeper) SaveOutbound(ctx sdk.Context, cctx *types.CrossChainTx, ballotIn
195201
outTxTssNonce := cctx.GetCurrentOutboundParam().TssNonce
196202

197203
cctx.GetCurrentOutboundParam().BallotIndex = ballotIndex
204+
198205
// #nosec G115 always in range
199206
k.GetObserverKeeper().RemoveFromPendingNonces(ctx, tssPubkey, receiverChain, int64(outTxTssNonce))
200207
k.RemoveOutboundTrackerFromStore(ctx, receiverChain, outTxTssNonce)
201208
ctx.Logger().
202-
Info(fmt.Sprintf("Remove tracker %s: , Block Height : %d ", getOutboundTrackerIndex(receiverChain, outTxTssNonce), ctx.BlockHeight()))
209+
Info("%s: Remove tracker %s: , Block Height : %d ", voteOutboundID, getOutboundTrackerIndex(receiverChain, outTxTssNonce), ctx.BlockHeight())
210+
203211
// This should set nonce to cctx only if a new revert is created.
204212
k.SetCctxAndNonceToCctxAndInboundHashToCctx(ctx, *cctx)
205213
}
206214

207215
func (k Keeper) ValidateOutboundMessage(ctx sdk.Context, msg types.MsgVoteOutbound) (types.CrossChainTx, error) {
208-
// check if CCTX exists and if the nonce matches
216+
// Check if CCTX exists and if the nonce matches.
209217
cctx, found := k.GetCrossChainTx(ctx, msg.CctxHash)
210218
if !found {
211-
return types.CrossChainTx{}, cosmoserrors.Wrap(
219+
return types.CrossChainTx{}, cosmoserrors.Wrapf(
212220
sdkerrors.ErrInvalidRequest,
213-
fmt.Sprintf("CCTX %s does not exist", msg.CctxHash),
214-
)
221+
"%s, CCTX %s does not exist", voteOutboundID, msg.CctxHash)
215222
}
223+
216224
if cctx.GetCurrentOutboundParam().TssNonce != msg.OutboundTssNonce {
217-
return types.CrossChainTx{}, cosmoserrors.Wrap(
225+
return types.CrossChainTx{}, cosmoserrors.Wrapf(
218226
sdkerrors.ErrInvalidRequest,
219-
fmt.Sprintf(
220-
"OutboundTssNonce %d does not match CCTX OutboundTssNonce %d",
221-
msg.OutboundTssNonce,
222-
cctx.GetCurrentOutboundParam().TssNonce,
223-
),
227+
"%s, OutboundTssNonce %d does not match CCTX OutboundTssNonce %d",
228+
voteOutboundID,
229+
msg.OutboundTssNonce,
230+
cctx.GetCurrentOutboundParam().TssNonce,
224231
)
225232
}
226-
// do not process an outbound vote if TSS is not found
233+
234+
// Do not process an outbound vote if TSS is not found.
227235
_, found = k.zetaObserverKeeper.GetTSS(ctx)
228236
if !found {
229-
return types.CrossChainTx{}, types.ErrCannotFindTSSKeys
237+
return types.CrossChainTx{}, cosmoserrors.Wrap(types.ErrCannotFindTSSKeys, voteOutboundID)
230238
}
239+
231240
if cctx.GetCurrentOutboundParam().ReceiverChainId != msg.OutboundChain {
232-
return types.CrossChainTx{}, cosmoserrors.Wrap(
241+
return types.CrossChainTx{}, cosmoserrors.Wrapf(
233242
sdkerrors.ErrInvalidRequest,
234-
fmt.Sprintf(
235-
"OutboundChain %d does not match CCTX OutboundChain %d",
236-
msg.OutboundChain,
237-
cctx.GetCurrentOutboundParam().ReceiverChainId,
238-
),
243+
"%s, OutboundChain %d does not match CCTX OutboundChain %d",
244+
voteOutboundID,
245+
msg.OutboundChain,
246+
cctx.GetCurrentOutboundParam().ReceiverChainId,
239247
)
240248
}
249+
241250
return cctx, nil
242251
}

x/observer/keeper/msg_server_update_observer.go

+10-16
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package keeper
22

33
import (
44
"context"
5-
"fmt"
65

76
errorsmod "cosmossdk.io/errors"
87
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -25,18 +24,16 @@ func (k msgServer) UpdateObserver(
2524
return nil, errorsmod.Wrap(types.ErrUpdateObserver, err.Error())
2625
}
2726
if !ok {
28-
return nil, errorsmod.Wrap(
27+
return nil, errorsmod.Wrapf(
2928
types.ErrUpdateObserver,
30-
fmt.Sprintf("Unable to update observer with update reason : %s", msg.UpdateReason),
31-
)
29+
"Unable to update observer with update reason : %s", msg.UpdateReason)
3230
}
3331

3432
// We do not use IsNonTombstonedObserver here because we want to allow tombstoned observers to be updated
3533
if !k.IsAddressPartOfObserverSet(ctx, msg.OldObserverAddress) {
36-
return nil, errorsmod.Wrap(
34+
return nil, errorsmod.Wrapf(
3735
types.ErrNotObserver,
38-
fmt.Sprintf("Observer address is not authorized : %s", msg.OldObserverAddress),
39-
)
36+
"Observer address is not authorized : %s", msg.OldObserverAddress)
4037
}
4138

4239
err = k.IsValidator(ctx, msg.NewObserverAddress)
@@ -53,10 +50,9 @@ func (k msgServer) UpdateObserver(
5350
// Update the node account with the new operator address
5451
nodeAccount, found := k.GetNodeAccount(ctx, msg.OldObserverAddress)
5552
if !found {
56-
return nil, errorsmod.Wrap(
53+
return nil, errorsmod.Wrapf(
5754
types.ErrNodeAccountNotFound,
58-
fmt.Sprintf("Observer node account not found : %s", msg.OldObserverAddress),
59-
)
55+
"Observer node account not found : %s", msg.OldObserverAddress)
6056
}
6157
newNodeAccount := nodeAccount
6258
newNodeAccount.Operator = msg.NewObserverAddress
@@ -68,15 +64,15 @@ func (k msgServer) UpdateObserver(
6864
// Check LastBlockObserver count just to be safe
6965
observerSet, found := k.GetObserverSet(ctx)
7066
if !found {
71-
return nil, errorsmod.Wrap(types.ErrObserverSetNotFound, fmt.Sprintf("Observer set not found"))
67+
return nil, errorsmod.Wrap(types.ErrObserverSetNotFound, "Observer set not found")
7268
}
7369
totalObserverCountCurrentBlock := observerSet.LenUint()
7470
lastBlockCount, found := k.GetLastObserverCount(ctx)
7571
if !found {
76-
return nil, errorsmod.Wrap(types.ErrLastObserverCountNotFound, fmt.Sprintf("Observer count not found"))
72+
return nil, errorsmod.Wrap(types.ErrLastObserverCountNotFound, "Observer count not found")
7773
}
7874
if lastBlockCount.Count != totalObserverCountCurrentBlock {
79-
return nil, errorsmod.Wrap(types.ErrUpdateObserver, fmt.Sprintf("Observer count mismatch"))
75+
return nil, errorsmod.Wrap(types.ErrUpdateObserver, "Observer count mismatch")
8076
}
8177
return &types.MsgUpdateObserverResponse{}, nil
8278
}
@@ -88,9 +84,7 @@ func (k Keeper) CheckUpdateReason(ctx sdk.Context, msg *types.MsgUpdateObserver)
8884
if msg.Creator != msg.OldObserverAddress {
8985
return false, errorsmod.Wrap(
9086
types.ErrUpdateObserver,
91-
fmt.Sprintf(
92-
"Creator address and old observer address need to be same for updating tombstoned observer",
93-
),
87+
"Creator address and old observer address need to be same for updating tombstoned observer",
9488
)
9589
}
9690
return k.IsOperatorTombstoned(ctx, msg.Creator)

0 commit comments

Comments
 (0)