code.vegaprotocol.io/vega@v0.79.0/core/client/eth/ethereum_confirmations_test.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package eth_test 17 18 import ( 19 "math/big" 20 "testing" 21 "time" 22 23 "code.vegaprotocol.io/vega/core/client/eth" 24 localMocks "code.vegaprotocol.io/vega/core/client/eth/mocks" 25 "code.vegaprotocol.io/vega/core/staking/mocks" 26 27 ethtypes "github.com/ethereum/go-ethereum/core/types" 28 "github.com/golang/mock/gomock" 29 "github.com/stretchr/testify/assert" 30 ) 31 32 func TestEthereumConfirmations(t *testing.T) { 33 ctrl := gomock.NewController(t) 34 ethClient := mocks.NewMockEthereumClientConfirmations(ctrl) 35 tim := localMocks.NewMockTime(ctrl) 36 cfg := eth.NewDefaultConfig() 37 cfg.RetryDelay.Duration = 15 * time.Second 38 ethCfns := eth.NewEthereumConfirmations(cfg, ethClient, tim, eth.FinalityStateFinalized) 39 defer ctrl.Finish() 40 41 ethCfns.UpdateConfirmations(30) 42 43 tim.EXPECT().Now().Times(1).Return(time.Unix(10, 0)) 44 // start a block 10 45 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(1). 46 Return(ðtypes.Header{Number: big.NewInt(10)}, nil) 47 48 // block 10, request 50, we are in the past, return err 49 assert.ErrorIs(t, ethCfns.Check(50), eth.ErrMissingConfirmations) 50 51 // request again but before buf size 52 // no request to eth 53 tim.EXPECT().Now().Times(1).Return(time.Unix(15, 0)) 54 55 // block 10, request 50, we are in the past, return err 56 assert.ErrorIs(t, ethCfns.Check(50), eth.ErrMissingConfirmations) 57 58 // request again but before buf size 59 // no request to eth 60 tim.EXPECT().Now().Times(1).Return(time.Unix(26, 0)) 61 // do block 50 == requested block 62 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(1). 63 Return(ðtypes.Header{Number: big.NewInt(50)}, nil) 64 65 // block 10, request 50, we are in the past, return err 66 assert.ErrorIs(t, ethCfns.Check(50), eth.ErrMissingConfirmations) 67 68 // request again but before buf size 69 // no request to eth 70 tim.EXPECT().Now().Times(1).Return(time.Unix(42, 0)) 71 // do block 79 > requested block < confirmations 72 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(1).Times(1). 73 Return(ðtypes.Header{Number: big.NewInt(79)}, nil) 74 75 // block 10, request 50, we are in the past, return err 76 assert.ErrorIs(t, ethCfns.Check(50), eth.ErrMissingConfirmations) 77 78 // request again but before buf size 79 tim.EXPECT().Now().Times(2).Return(time.Unix(58, 0)) 80 // do block 80 > requested block == confirmations, and also block is seen as finalized 81 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(2). 82 Return(ðtypes.Header{Number: big.NewInt(80)}, nil) 83 84 assert.NoError(t, ethCfns.Check(50)) 85 86 // request again but before buf size 87 // no request to eth 88 tim.EXPECT().Now().Times(2).Return(time.Unix(1000, 0)) 89 // do block 80 > requested block == confirmations 90 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(2). 91 Return(ðtypes.Header{Number: big.NewInt(100)}, nil) 92 93 // block 10, request 50, we are in the past, return err 94 assert.NoError(t, ethCfns.Check(50)) 95 } 96 97 func TestBlockFinalisation(t *testing.T) { 98 ctrl := gomock.NewController(t) 99 ethClient := mocks.NewMockEthereumClientConfirmations(ctrl) 100 tim := localMocks.NewMockTime(ctrl) 101 cfg := eth.NewDefaultConfig() 102 cfg.RetryDelay.Duration = 15 * time.Second 103 ethCfns := eth.NewEthereumConfirmations(cfg, ethClient, tim, eth.FinalityStateFinalized) 104 defer ctrl.Finish() 105 106 ethCfns.UpdateConfirmations(10) 107 108 // testing with block 50 where we need 10 confirmations 109 // current Ethereum block is 70 so we have enough confirmations, but finalized block is 49 110 tim.EXPECT().Now().Times(2).Return(time.Unix(10, 0)) 111 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(1). 112 Return(ðtypes.Header{Number: big.NewInt(70)}, nil) 113 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(1). 114 Return(ðtypes.Header{Number: big.NewInt(49)}, nil) 115 116 // block 10, request 50, we are in the past, return err 117 assert.ErrorIs(t, ethCfns.Check(50), eth.ErrBlockNotFinalized) 118 119 // now we are passed enough confirmations AND the block has been finalized 120 tim.EXPECT().Now().Times(2).Return(time.Unix(60, 0)) 121 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(1). 122 Return(ðtypes.Header{Number: big.NewInt(70)}, nil) 123 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(1). 124 Return(ðtypes.Header{Number: big.NewInt(50)}, nil) 125 assert.NoError(t, ethCfns.Check(50)) 126 } 127 128 func TestCheckRequiredConfirmations(t *testing.T) { 129 ctrl := gomock.NewController(t) 130 ethClient := mocks.NewMockEthereumClientConfirmations(ctrl) 131 tim := localMocks.NewMockTime(ctrl) 132 cfg := eth.NewDefaultConfig() 133 cfg.RetryDelay.Duration = 15 * time.Second 134 ethCfns := eth.NewEthereumConfirmations(cfg, ethClient, tim, eth.FinalityStateFinalized) 135 defer ctrl.Finish() 136 137 tim.EXPECT().Now().Times(1).Return(time.Unix(10, 0)) 138 // start a block 10 139 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(1). 140 Return(ðtypes.Header{Number: big.NewInt(10)}, nil) 141 142 // block 10, request 50, we are in the past, return err 143 assert.ErrorIs(t, ethCfns.CheckRequiredConfirmations(50, 30), eth.ErrMissingConfirmations) 144 145 tim.EXPECT().Now().Times(1).Return(time.Unix(58, 0)) 146 // do block 80 > requested block == confirmations 147 ethClient.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Times(1). 148 Return(ðtypes.Header{Number: big.NewInt(80)}, nil) 149 150 // block 10, request 50, we are in the past, return err 151 assert.NoError(t, ethCfns.CheckRequiredConfirmations(50, 30)) 152 153 tim.EXPECT().Now().Times(1).Return(time.Unix(59, 0)) 154 assert.ErrorIs(t, ethCfns.CheckRequiredConfirmations(50, 40), eth.ErrMissingConfirmations) 155 }