@@ -14,12 +14,10 @@ import (
1414 ethtypes "github.com/ethereum/go-ethereum/core/types"
1515 cttypes "github.com/tendermint/tendermint/rpc/core/types"
1616 ttypes "github.com/tendermint/tendermint/types"
17- "go.vocdoni.io/dvote/census"
1817 "go.vocdoni.io/dvote/crypto/ethereum"
1918 "go.vocdoni.io/dvote/data"
2019 "go.vocdoni.io/dvote/types"
2120 "go.vocdoni.io/dvote/vochain"
22- "go.vocdoni.io/dvote/vochain/scrutinizer"
2321 "go.vocdoni.io/proto/build/go/models"
2422
2523 "github.com/ethereum/go-ethereum/ethclient"
@@ -28,7 +26,7 @@ import (
2826)
2927
3028const (
31- readBlocksPast = 100
29+ readBlocksPast = 200
3230)
3331
3432var blockConfirmThreshold = map [models.SourceNetworkId ]time.Duration {
@@ -42,8 +40,6 @@ var blockConfirmThreshold = map[models.SourceNetworkId]time.Duration{
4240type EthereumEvents struct {
4341 // contracts handle
4442 VotingHandle * ethereumhandler.EthereumHandler
45- // dial web3 addresses
46- DialAddrs []string
4743 // list of handler functions that will be called on events
4844 // TODO: add context on callbacks
4945 // TODO: return errors on callbacks
@@ -52,20 +48,18 @@ type EthereumEvents struct {
5248 Signer * ethereum.SignKeys
5349 // VochainApp is a pointer to the Vochain BaseApplication allowing to call SendTx method
5450 VochainApp * vochain.BaseApplication
55- // Census is the census manager service
56- Census CensusManager
5751 // EventProcessor handles events pending to process
5852 EventProcessor * EventProcessor
59- // Scrutinizer
60- Scrutinizer * scrutinizer.Scrutinizer
6153 // EthereumWhiteListAddrs
6254 EthereumWhiteListAddrs map [common.Address ]bool
6355 // ContractsAddress
6456 ContractsAddress []common.Address
6557 // ContractsInfo holds useful info for working with the desired contracts
6658 ContractsInfo map [string ]* ethereumhandler.EthereumContract
6759 // EthereumLastKnownBlock keeps track of the latest Ethereum known block
68- EthereumLastKnownBlock atomic.Value
60+ EthereumLastKnownBlock uint64
61+ // block confirm threshold for the network
62+ blockConfirmThreshold time.Duration
6963}
7064
7165type timedEvent struct {
@@ -105,8 +99,6 @@ func NewEthEvents(
10599 contracts map [string ]* ethereumhandler.EthereumContract ,
106100 srcNetworkId models.SourceNetworkId ,
107101 signer * ethereum.SignKeys ,
108- w3Endpoints []string ,
109- cens * census.Manager ,
110102 vocapp * vochain.BaseApplication ,
111103 ethereumWhiteList []string ,
112104) (* EthereumEvents , error ) {
@@ -136,8 +128,6 @@ func NewEthEvents(
136128 srcNetworkId , confirmThreshold )
137129 ethev := & EthereumEvents {
138130 Signer : signer ,
139- DialAddrs : w3Endpoints ,
140- Census : cens ,
141131 VochainApp : vocapp ,
142132 EventProcessor : & EventProcessor {
143133 Events : make (chan ethtypes.Log ),
@@ -147,6 +137,7 @@ func NewEthEvents(
147137 EthereumWhiteListAddrs : secureAddrList ,
148138 ContractsAddress : contractsAddress ,
149139 ContractsInfo : contracts ,
140+ blockConfirmThreshold : confirmThreshold ,
150141 }
151142
152143 return ethev , nil
@@ -167,29 +158,24 @@ func (ev *EthereumEvents) SubscribeEthereumEventLogs(ctx context.Context) {
167158 tctx , cancel := context .WithTimeout (ctx , types .EthereumReadTimeout )
168159 defer cancel ()
169160 var err error
170- uLastBlockNumber , err := ev .VotingHandle .EthereumClient .BlockNumber (tctx )
161+ lastBlockNumber , err := ev .VotingHandle .EthereumClient .BlockNumber (tctx )
171162 if err != nil {
172163 log .Fatalf ("cannot get last block number: (%v)" , err )
173164 }
174- lastBlockNumber := int64 (uLastBlockNumber )
175- fromBlock := ev .EthereumLastKnownBlock .Load ().(int64 )
176- if fromBlock == 0 {
177- ev .EthereumLastKnownBlock .Store (lastBlockNumber )
178- fromBlock = lastBlockNumber
179- }
165+ atomic .StoreUint64 (& ev .EthereumLastKnownBlock , lastBlockNumber )
180166
181167 // For security, even if subscribe only, force to process
182168 // from some past blocks defined by `readBlocksPast`
183- if err := ev .processEventLogsFromTo (ctx , fromBlock - readBlocksPast ,
169+ if err := ev .processEventLogsFromTo (ctx , lastBlockNumber - readBlocksPast ,
184170 lastBlockNumber , ev .VotingHandle .EthereumClient ); err != nil {
185171 log .Errorf ("cannot process event logs: %v" , err )
186172 }
187173
188174 // Subscribing from latest known block
189- log .Infof ("subscribing to Ethereum Events from block %d" , fromBlock )
175+ log .Infof ("subscribing to Ethereum Events from block %d" , lastBlockNumber )
190176 query := eth.FilterQuery {
191177 Addresses : ev .ContractsAddress ,
192- FromBlock : big .NewInt ( fromBlock ),
178+ FromBlock : new ( big.Int ). SetUint64 ( lastBlockNumber ),
193179 }
194180 logs := make (chan ethtypes.Log , 30 ) // give it some buffer as recommended by the package library
195181 var sub eth.Subscription
@@ -204,38 +190,44 @@ func (ev *EthereumEvents) SubscribeEthereumEventLogs(ctx context.Context) {
204190 }
205191
206192 // Monitorize ethereum client connection
207- connFailure := make (chan bool , 1 )
208- go func (chan bool ) {
193+ connFailure := make (chan error , 1 )
194+ go func (chan error ) {
195+ time .Sleep (ev .blockConfirmThreshold )
209196 for {
210- time .Sleep (time .Second * 5 )
211- tctx , cancel := context .WithTimeout (ctx , types .EthereumReadTimeout )
212- defer cancel ()
213- block , err := ev .VotingHandle .EthereumClient .BlockNumber (tctx )
214- if err != nil {
215- log .Warnf ("cannot check ethereum connection while running the event processor, %s" , err )
216- connFailure <- false
197+ select {
198+ case <- ctx .Done ():
217199 return
200+ default :
201+ tctx , cancel := context .WithTimeout (ctx , types .EthereumReadTimeout )
202+ block , err := ev .VotingHandle .EthereumClient .BlockNumber (tctx )
203+ cancel ()
204+ if err != nil {
205+ connFailure <- err
206+ return
207+ }
208+ if atomic .LoadUint64 (& ev .EthereumLastKnownBlock ) >= block {
209+ connFailure <- fmt .Errorf ("web3 frozen, block have not changed on the last %s" ,
210+ ev .blockConfirmThreshold )
211+ return
212+ }
213+ atomic .StoreUint64 (& ev .EthereumLastKnownBlock , block )
214+ time .Sleep (ev .blockConfirmThreshold )
218215 }
219- ev .EthereumLastKnownBlock .Store (int64 (block ))
220216 }
221217 }(connFailure )
222218
223219 // Block forever and start processing events
224220 for {
225221 select {
226- case <- sub .Err ():
222+ case err := <- sub .Err ():
227223 ev .EventProcessor .eventProcessorRunning = false
228- ev .VotingHandle = nil
229- log .Warn ("ethereum events subscription error on channel" )
230- log .Infof ("restarting ethereum events subscription with web3: %+v" , ev .DialAddrs )
224+ log .Warnf ("ethereum events connection error: %v" , err )
231225 return
232226 case event := <- logs :
233227 ev .EventProcessor .Events <- event
234- case <- connFailure :
228+ case err := <- connFailure :
235229 ev .EventProcessor .eventProcessorRunning = false
236- ev .VotingHandle = nil
237- log .Warn ("ethereum events subscription error on channel" )
238- log .Infof ("restarting ethereum events subscription with web3: %+v" , ev .DialAddrs )
230+ log .Warnf ("ethereum events connection failure: %v" , err )
239231 return
240232 }
241233 }
@@ -244,7 +236,7 @@ func (ev *EthereumEvents) SubscribeEthereumEventLogs(ctx context.Context) {
244236// ReadEthereumEventLogs reads the oracle
245237// defined smart contract and looks for events.
246238func (ev * EthereumEvents ) processEventLogsFromTo (ctx context.Context ,
247- from , to int64 , client * ethclient.Client ) error {
239+ from , to uint64 , client * ethclient.Client ) error {
248240 for name , contract := range ev .ContractsInfo {
249241 if ! contract .ListenForEvents {
250242 continue
@@ -254,8 +246,8 @@ func (ev *EthereumEvents) processEventLogsFromTo(ctx context.Context,
254246 }
255247 log .Infof ("reading ethereum events from block %d to %d" , from , to )
256248 query := eth.FilterQuery {
257- FromBlock : big .NewInt (from ),
258- ToBlock : big .NewInt (to ),
249+ FromBlock : new ( big.Int ). SetUint64 (from ),
250+ ToBlock : new ( big.Int ). SetUint64 (to ),
259251 Addresses : ev .ContractsAddress ,
260252 }
261253
0 commit comments