From 979ba9e3c6979eb277f8606ab3832cbd0da9411c Mon Sep 17 00:00:00 2001 From: Mostafa Date: Thu, 1 Feb 2024 05:16:59 +0800 Subject: [PATCH 1/2] fix: local node and claim tests are fixed --- client/client_mgr.go | 117 +++++++++++++++--------------------------- engine/engine.go | 10 ++-- engine/engine_test.go | 100 +++++++++++++++++++----------------- 3 files changed, 99 insertions(+), 128 deletions(-) diff --git a/client/client_mgr.go b/client/client_mgr.go index c5aa5f48..6758ea46 100644 --- a/client/client_mgr.go +++ b/client/client_mgr.go @@ -8,17 +8,22 @@ import ( ) type Mgr struct { - clients map[string]IClient + clients []IClient } func NewClientMgr() *Mgr { return &Mgr{ - clients: make(map[string]IClient), + clients: make([]IClient, 0), } } -func (cm *Mgr) AddClient(addr string, c IClient) { - cm.clients[addr] = c +func (cm *Mgr) AddClient(c IClient) { + cm.clients = append(cm.clients, c) +} + +// NOTE: local client is always the first client +func (cm *Mgr) getLocalClient() IClient { + return cm.clients[0] } func (cm *Mgr) GetRandomClient() IClient { @@ -30,52 +35,36 @@ func (cm *Mgr) GetRandomClient() IClient { } func (cm *Mgr) GetBlockchainInfo() (*pactus.GetBlockchainInfoResponse, error) { - for _, c := range cm.clients { - info, err := c.GetBlockchainInfo() - if err != nil { - continue - } - return info, nil + localClient := cm.getLocalClient() + info, err := localClient.GetBlockchainInfo() + if err != nil { + return nil, err } + return info, nil - return nil, errors.New("unable to get blockchain info") } func (cm *Mgr) GetBlockchainHeight() (uint32, error) { - for _, c := range cm.clients { - height, err := c.GetBlockchainHeight() - if err != nil { - continue - } - return height, nil + localClient := cm.getLocalClient() + height, err := localClient.GetBlockchainHeight() + if err != nil { + return 0, err } - - return 0, errors.New("unable to get blockchain height") + return height, nil } func (cm *Mgr) GetLastBlockTime() (uint32, uint32) { - var lastBlockTime uint32 = 0 - var lastBlockHeight uint32 = 0 - for _, c := range cm.clients { - t, h, err := c.LastBlockTime() - if err != nil { - continue - } - if t > lastBlockTime { - lastBlockTime = t - lastBlockHeight = h - } + localClient := cm.getLocalClient() + lastBlockTime, lastBlockHeight, err := localClient.LastBlockTime() + if err != nil { + return 0, 0 } return lastBlockTime, lastBlockHeight } func (cm *Mgr) GetNetworkInfo() (*pactus.GetNetworkInfoResponse, error) { - for name, c := range cm.clients { - if name == "local-node" { - continue - } - + for _, c := range cm.clients { info, err := c.GetNetworkInfo() if err != nil { continue @@ -87,11 +76,7 @@ func (cm *Mgr) GetNetworkInfo() (*pactus.GetNetworkInfoResponse, error) { } func (cm *Mgr) GetPeerInfoFirstVal(address string) (*pactus.PeerInfo, error) { - for name, c := range cm.clients { - if name == "local-node" { - continue - } - + for _, c := range cm.clients { networkInfo, err := c.GetNetworkInfo() if err != nil { continue @@ -135,53 +120,31 @@ func (cm *Mgr) GetPeerInfo(address string) (*pactus.PeerInfo, error) { return nil, errors.New("peer does not exist") } -func (cm *Mgr) IsStakedValidator(address string) bool { - c, ok := cm.clients["local-node"] - if ok { - val, err := c.GetValidatorInfo(address) - if err != nil { - return false - } - return val.Validator.Stake > 0 - } - - return false -} - func (cm *Mgr) GetValidatorInfo(address string) (*pactus.GetValidatorResponse, error) { - for _, c := range cm.clients { - val, err := c.GetValidatorInfo(address) - if err != nil { - continue - } - return val, nil + localClient := cm.getLocalClient() + val, err := localClient.GetValidatorInfo(address) + if err != nil { + return nil, err } - - return nil, errors.New("unable to get validator info") + return val, nil } func (cm *Mgr) GetValidatorInfoByNumber(num int32) (*pactus.GetValidatorResponse, error) { - for _, c := range cm.clients { - val, err := c.GetValidatorInfoByNumber(num) - if err != nil { - continue - } - return val, nil + localClient := cm.getLocalClient() + val, err := localClient.GetValidatorInfoByNumber(num) + if err != nil { + return nil, err } - - return nil, errors.New("unable to get validator info") + return val, nil } func (cm *Mgr) GetTransactionData(txID string) (*pactus.GetTransactionResponse, error) { - for _, c := range cm.clients { - txData, err := c.GetTransactionData(txID) - if err != nil { - continue - } - return txData, nil + localClient := cm.getLocalClient() + txData, err := localClient.GetTransactionData(txID) + if err != nil { + return nil, err } - - return nil, errors.New("unable to get transaction data") + return txData, nil } func (cm *Mgr) Stop() { diff --git a/engine/engine.go b/engine/engine.go index e28e8a1f..c6a2d4f7 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -26,20 +26,20 @@ type BotEngine struct { func NewBotEngine(cfg *config.Config) (IEngine, error) { cm := client.NewClientMgr() - c, err := client.NewClient(cfg.LocalNode) + localClient, err := client.NewClient(cfg.LocalNode) if err != nil { log.Error("can't make a new local client", "err", err, "addr", cfg.LocalNode) return nil, err } - cm.AddClient("local-node", c) + cm.AddClient(localClient) for _, nn := range cfg.NetworkNodes { c, err := client.NewClient(nn) if err != nil { log.Error("can't add new network node client", "err", err, "addr", nn) } - cm.AddClient("client", c) + cm.AddClient(c) } // initializing logger global instance. @@ -181,8 +181,8 @@ func (be *BotEngine) Claim(discordID string, testnetAddr string, mainnetAddr str be.logger.Info("new claim request", "mainnetAddr", mainnetAddr, "testnetAddr", testnetAddr, "discordID", discordID) - isValidator := be.Cm.IsStakedValidator(mainnetAddr) - if isValidator { + valInfo, _ := be.Cm.GetValidatorInfo(mainnetAddr) + if valInfo != nil { return "", errors.New("this address is already a staked validator") } diff --git a/engine/engine_test.go b/engine/engine_test.go index 34342f1c..ca1aeb16 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -2,6 +2,7 @@ package engine import ( "errors" + "fmt" "testing" "time" @@ -25,7 +26,7 @@ func setup(t *testing.T) (*BotEngine, *client.MockIClient, *rpstore.MockIStore, mockClient := client.NewMockIClient(ctrl) cm := client.NewClientMgr() - cm.AddClient("local-node", mockClient) + cm.AddClient(mockClient) // mocking mockWallet. mockWallet := wallet.NewMockIWallet(ctrl) @@ -140,9 +141,9 @@ func TestNodeInfo(t *testing.T) { } func TestClaim(t *testing.T) { - eng, client, store, wallet := setup(t) - t.Run("everything normal and good", func(t *testing.T) { + eng, client, store, wallet := setup(t) + mainnetAddr := "mainnet-addr" testnetAddr := "testnet-addr" pubKey := "public-key" @@ -156,12 +157,8 @@ func TestClaim(t *testing.T) { ).MaxTimes(2) client.EXPECT().GetValidatorInfo(mainnetAddr).Return( - &pactus.GetValidatorResponse{ - Validator: &pactus.ValidatorInfo{ - Stake: 0, - }, - }, nil, - ).AnyTimes() + nil, fmt.Errorf("not found"), + ) store.EXPECT().ClaimerInfo(testnetAddr).Return( &rpstore.Claimer{ @@ -194,21 +191,47 @@ func TestClaim(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, expectedTx, txID) - //! can't claim twice: + //! can't claim twice immediately before transaction is committed: + client.EXPECT().GetValidatorInfo(mainnetAddr).Return( + nil, fmt.Errorf("not found"), + ).Times(1) + store.EXPECT().ClaimerInfo(testnetAddr).Return( &rpstore.Claimer{ DiscordID: discordID, TotalReward: amount, ClaimedTxID: txID, }, - ) + ).Times(1) expectedTx, err = eng.Claim(discordID, testnetAddr, mainnetAddr) assert.Error(t, err) assert.Empty(t, expectedTx) }) + t.Run("should fail, already staked", func(t *testing.T) { + eng, client, _, _ := setup(t) + + mainnetAddr := "mainnet-addr-fail-balance" + testnetAddr := "testnet-addr-fail-balance" + discordID := "123456789-already staked" + + client.EXPECT().GetValidatorInfo(mainnetAddr).Return( + &pactus.GetValidatorResponse{ + Validator: &pactus.ValidatorInfo{ + Stake: 1, + }, + }, nil, + ).Times(1) + + expectedTx, err := eng.Claim(discordID, testnetAddr, mainnetAddr) + assert.EqualError(t, err, "this address is already a staked validator") + assert.Empty(t, expectedTx) + }) + t.Run("should fail, low balance", func(t *testing.T) { + eng, client, _, wallet := setup(t) + mainnetAddr := "mainnet-addr-fail-balance" testnetAddr := "testnet-addr-fail-balance" discordID := "123456789-fail-balance" @@ -218,11 +241,7 @@ func TestClaim(t *testing.T) { ) client.EXPECT().GetValidatorInfo(mainnetAddr).Return( - &pactus.GetValidatorResponse{ - Validator: &pactus.ValidatorInfo{ - Stake: 0, - }, - }, nil, + nil, fmt.Errorf("not found"), ) expectedTx, err := eng.Claim(discordID, testnetAddr, mainnetAddr) assert.EqualError(t, err, "insufficient wallet balance") @@ -230,6 +249,8 @@ func TestClaim(t *testing.T) { }) t.Run("should fail, claimer not found", func(t *testing.T) { + eng, client, store, wallet := setup(t) + mainnetAddr := "mainnet-addr-fail-notfound" testnetAddr := "testnet-addr-fail-notfound" discordID := "123456789-fail-notfound" @@ -239,11 +260,7 @@ func TestClaim(t *testing.T) { ) client.EXPECT().GetValidatorInfo(mainnetAddr).Return( - &pactus.GetValidatorResponse{ - Validator: &pactus.ValidatorInfo{ - Stake: 0, - }, - }, nil, + nil, fmt.Errorf("not found"), ) store.EXPECT().ClaimerInfo(testnetAddr).Return( @@ -256,6 +273,8 @@ func TestClaim(t *testing.T) { }) t.Run("should fail, different Discord ID", func(t *testing.T) { + eng, client, store, wallet := setup(t) + mainnetAddr := "mainnet-addr-fail-different-id" testnetAddr := "testnet-addr-fail-different-id" discordID := "123456789-fail-different-id" @@ -265,11 +284,7 @@ func TestClaim(t *testing.T) { ) client.EXPECT().GetValidatorInfo(mainnetAddr).Return( - &pactus.GetValidatorResponse{ - Validator: &pactus.ValidatorInfo{ - Stake: 0, - }, - }, nil, + nil, fmt.Errorf("not found"), ) store.EXPECT().ClaimerInfo(testnetAddr).Return( @@ -284,6 +299,8 @@ func TestClaim(t *testing.T) { }) t.Run("should fail, not first validator address", func(t *testing.T) { + eng, client, store, wallet := setup(t) + mainnetAddr := "mainnet-addr-fail-not-first-validator" testnetAddr := "testnet-addr-fail-not-first-validator" discordID := "123456789-fail-not-first-validator" @@ -293,11 +310,7 @@ func TestClaim(t *testing.T) { ) client.EXPECT().GetValidatorInfo(mainnetAddr).Return( - &pactus.GetValidatorResponse{ - Validator: &pactus.ValidatorInfo{ - Stake: 0, - }, - }, nil, + nil, fmt.Errorf("not found"), ) store.EXPECT().ClaimerInfo(testnetAddr).Return( @@ -323,6 +336,8 @@ func TestClaim(t *testing.T) { }) t.Run("should fail, validator not found", func(t *testing.T) { + eng, client, store, wallet := setup(t) + mainnetAddr := "mainnet-addr-fail-validator-not-found" testnetAddr := "testnet-addr-fail-validator-not-found" discordID := "123456789-fail-validator-not-found" @@ -332,11 +347,7 @@ func TestClaim(t *testing.T) { ) client.EXPECT().GetValidatorInfo(mainnetAddr).Return( - &pactus.GetValidatorResponse{ - Validator: &pactus.ValidatorInfo{ - Stake: 0, - }, - }, nil, + nil, fmt.Errorf("not found"), ) store.EXPECT().ClaimerInfo(testnetAddr).Return( @@ -362,6 +373,8 @@ func TestClaim(t *testing.T) { }) t.Run("should fail, empty transaction hash", func(t *testing.T) { + eng, client, store, wallet := setup(t) + mainnetAddr := "mainnet-addr-fail-empty-tx-hash" testnetAddr := "testnet-addr-fail-empty-tx-hash" pubKey := "public-key-fail-empty-tx-hash" @@ -374,11 +387,7 @@ func TestClaim(t *testing.T) { ) client.EXPECT().GetValidatorInfo(mainnetAddr).Return( - &pactus.GetValidatorResponse{ - Validator: &pactus.ValidatorInfo{ - Stake: 0, - }, - }, nil, + nil, fmt.Errorf("not found"), ) store.EXPECT().ClaimerInfo(testnetAddr).Return( @@ -410,6 +419,8 @@ func TestClaim(t *testing.T) { }) t.Run("should panic, add claimer failed", func(t *testing.T) { + eng, client, store, wallet := setup(t) + mainnetAddr := "mainnet-addr-panic-add-claimer-failed" testnetAddr := "testnet-addr-panic-add-claimer-failed" pubKey := "public-key-panic-add-claimer-failed" @@ -423,12 +434,9 @@ func TestClaim(t *testing.T) { ) client.EXPECT().GetValidatorInfo(mainnetAddr).Return( - &pactus.GetValidatorResponse{ - Validator: &pactus.ValidatorInfo{ - Stake: 0, - }, - }, nil, + nil, fmt.Errorf("not found"), ) + store.EXPECT().ClaimerInfo(testnetAddr).Return( &rpstore.Claimer{ DiscordID: discordID, From 215874bb2b422ce3b51aa2efa3c248755a7458b0 Mon Sep 17 00:00:00 2001 From: Mostafa Date: Thu, 1 Feb 2024 05:18:00 +0800 Subject: [PATCH 2/2] fixing linting issues --- client/client_mgr.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/client_mgr.go b/client/client_mgr.go index 6758ea46..dc6cebf8 100644 --- a/client/client_mgr.go +++ b/client/client_mgr.go @@ -21,7 +21,7 @@ func (cm *Mgr) AddClient(c IClient) { cm.clients = append(cm.clients, c) } -// NOTE: local client is always the first client +// NOTE: local client is always the first client. func (cm *Mgr) getLocalClient() IClient { return cm.clients[0] } @@ -41,7 +41,6 @@ func (cm *Mgr) GetBlockchainInfo() (*pactus.GetBlockchainInfoResponse, error) { return nil, err } return info, nil - } func (cm *Mgr) GetBlockchainHeight() (uint32, error) {