Node: Support for EVM watcher safe blocks (#1727)
* Node: Support for EVM watcher safe blocks * Fix merge error * Add check of publishSafeBlocks if not useFinalized
This commit is contained in:
parent
091ee0877d
commit
95fd892bec
|
@ -18,6 +18,7 @@ type NewBlock struct {
|
||||||
Number *big.Int
|
Number *big.Int
|
||||||
Hash common.Hash
|
Hash common.Hash
|
||||||
L1BlockNumber *big.Int // This is only populated on some chains (Arbitrum)
|
L1BlockNumber *big.Int // This is only populated on some chains (Arbitrum)
|
||||||
|
Safe bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connector exposes Wormhole-specific interactions with an EVM-based network
|
// Connector exposes Wormhole-specific interactions with an EVM-based network
|
||||||
|
|
|
@ -25,16 +25,21 @@ type BlockPollConnector struct {
|
||||||
Connector
|
Connector
|
||||||
Delay time.Duration
|
Delay time.Duration
|
||||||
useFinalized bool
|
useFinalized bool
|
||||||
|
publishSafeBlocks bool
|
||||||
finalizer PollFinalizer
|
finalizer PollFinalizer
|
||||||
blockFeed ethEvent.Feed
|
blockFeed ethEvent.Feed
|
||||||
errFeed ethEvent.Feed
|
errFeed ethEvent.Feed
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBlockPollConnector(ctx context.Context, baseConnector Connector, finalizer PollFinalizer, delay time.Duration, useFinalized bool) (*BlockPollConnector, error) {
|
func NewBlockPollConnector(ctx context.Context, baseConnector Connector, finalizer PollFinalizer, delay time.Duration, useFinalized bool, publishSafeBlocks bool) (*BlockPollConnector, error) {
|
||||||
|
if publishSafeBlocks && !useFinalized {
|
||||||
|
return nil, fmt.Errorf("publishSafeBlocks may only be enabled if useFinalized is enabled")
|
||||||
|
}
|
||||||
connector := &BlockPollConnector{
|
connector := &BlockPollConnector{
|
||||||
Connector: baseConnector,
|
Connector: baseConnector,
|
||||||
Delay: delay,
|
Delay: delay,
|
||||||
useFinalized: useFinalized,
|
useFinalized: useFinalized,
|
||||||
|
publishSafeBlocks: publishSafeBlocks,
|
||||||
finalizer: finalizer,
|
finalizer: finalizer,
|
||||||
}
|
}
|
||||||
err := supervisor.Run(ctx, "blockPoller", connector.run)
|
err := supervisor.Run(ctx, "blockPoller", connector.run)
|
||||||
|
@ -47,11 +52,19 @@ func NewBlockPollConnector(ctx context.Context, baseConnector Connector, finaliz
|
||||||
func (b *BlockPollConnector) run(ctx context.Context) error {
|
func (b *BlockPollConnector) run(ctx context.Context) error {
|
||||||
logger := supervisor.Logger(ctx).With(zap.String("eth_network", b.Connector.NetworkName()))
|
logger := supervisor.Logger(ctx).With(zap.String("eth_network", b.Connector.NetworkName()))
|
||||||
|
|
||||||
lastBlock, err := b.getBlock(ctx, logger, nil)
|
lastBlock, err := b.getBlock(ctx, logger, nil, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var lastSafeBlock *NewBlock
|
||||||
|
if b.publishSafeBlocks {
|
||||||
|
lastSafeBlock, err = b.getBlock(ctx, logger, nil, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
timer := time.NewTimer(time.Millisecond) // Start immediately.
|
timer := time.NewTimer(time.Millisecond) // Start immediately.
|
||||||
supervisor.Signal(ctx, supervisor.SignalHealthy)
|
supervisor.Signal(ctx, supervisor.SignalHealthy)
|
||||||
|
|
||||||
|
@ -62,17 +75,30 @@ func (b *BlockPollConnector) run(ctx context.Context) error {
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
for count := 0; count < 3; count++ {
|
for count := 0; count < 3; count++ {
|
||||||
lastBlock, err = b.pollBlocks(ctx, logger, lastBlock)
|
lastBlock, err = b.pollBlocks(ctx, logger, lastBlock, false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
logger.Error("polling encountered an error", zap.Error(err))
|
logger.Error("polling of block encountered an error", zap.Error(err))
|
||||||
|
|
||||||
// Wait an interval before trying again. We stay in this loop so that we
|
// Wait an interval before trying again. We stay in this loop so that we
|
||||||
// try up to three times before causing the watcher to restart.
|
// try up to three times before causing the watcher to restart.
|
||||||
time.Sleep(b.Delay)
|
time.Sleep(b.Delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err == nil && b.publishSafeBlocks {
|
||||||
|
for count := 0; count < 3; count++ {
|
||||||
|
lastSafeBlock, err = b.pollBlocks(ctx, logger, lastSafeBlock, true)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
logger.Error("polling of safe block encountered an error", zap.Error(err))
|
||||||
|
|
||||||
|
// Same wait as above.
|
||||||
|
time.Sleep(b.Delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.errFeed.Send(fmt.Sprint("polling encountered an error: ", err))
|
b.errFeed.Send(fmt.Sprint("polling encountered an error: ", err))
|
||||||
}
|
}
|
||||||
|
@ -81,7 +107,7 @@ func (b *BlockPollConnector) run(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BlockPollConnector) pollBlocks(ctx context.Context, logger *zap.Logger, lastBlock *NewBlock) (lastPublishedBlock *NewBlock, retErr error) {
|
func (b *BlockPollConnector) pollBlocks(ctx context.Context, logger *zap.Logger, lastBlock *NewBlock, safe bool) (lastPublishedBlock *NewBlock, retErr error) {
|
||||||
// Some of the testnet providers (like the one we are using for Arbitrum) limit how many transactions we can do. When that happens, the call hangs.
|
// Some of the testnet providers (like the one we are using for Arbitrum) limit how many transactions we can do. When that happens, the call hangs.
|
||||||
// Use a timeout so that the call will fail and the runable will get restarted. This should not happen in mainnet, but if it does, we will need to
|
// Use a timeout so that the call will fail and the runable will get restarted. This should not happen in mainnet, but if it does, we will need to
|
||||||
// investigate why the runable is dying and fix the underlying problem.
|
// investigate why the runable is dying and fix the underlying problem.
|
||||||
|
@ -94,7 +120,7 @@ func (b *BlockPollConnector) pollBlocks(ctx context.Context, logger *zap.Logger,
|
||||||
// Fetch the latest block on the chain
|
// Fetch the latest block on the chain
|
||||||
// We could do this on every iteration such that if a new block is created while this function is being executed,
|
// We could do this on every iteration such that if a new block is created while this function is being executed,
|
||||||
// it would automatically fetch new blocks but in order to reduce API load this will be done on the next iteration.
|
// it would automatically fetch new blocks but in order to reduce API load this will be done on the next iteration.
|
||||||
latestBlock, err := b.getBlock(timeout, logger, nil)
|
latestBlock, err := b.getBlock(timeout, logger, nil, safe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to look up latest block",
|
logger.Error("failed to look up latest block",
|
||||||
zap.Uint64("lastSeenBlock", lastBlock.Number.Uint64()), zap.Error(err))
|
zap.Uint64("lastSeenBlock", lastBlock.Number.Uint64()), zap.Error(err))
|
||||||
|
@ -108,7 +134,7 @@ func (b *BlockPollConnector) pollBlocks(ctx context.Context, logger *zap.Logger,
|
||||||
|
|
||||||
// Try to fetch the next block between lastBlock and latestBlock
|
// Try to fetch the next block between lastBlock and latestBlock
|
||||||
nextBlockNumber := new(big.Int).Add(lastPublishedBlock.Number, big.NewInt(1))
|
nextBlockNumber := new(big.Int).Add(lastPublishedBlock.Number, big.NewInt(1))
|
||||||
block, err := b.getBlock(timeout, logger, nextBlockNumber)
|
block, err := b.getBlock(timeout, logger, nextBlockNumber, safe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to fetch next block",
|
logger.Error("failed to fetch next block",
|
||||||
zap.Uint64("block", nextBlockNumber.Uint64()), zap.Error(err))
|
zap.Uint64("block", nextBlockNumber.Uint64()), zap.Error(err))
|
||||||
|
@ -164,17 +190,21 @@ func (b *BlockPollConnector) SubscribeForBlocks(ctx context.Context, sink chan<-
|
||||||
return sub, nil
|
return sub, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BlockPollConnector) getBlock(ctx context.Context, logger *zap.Logger, number *big.Int) (*NewBlock, error) {
|
func (b *BlockPollConnector) getBlock(ctx context.Context, logger *zap.Logger, number *big.Int, safe bool) (*NewBlock, error) {
|
||||||
return getBlock(ctx, logger, b.Connector, number, b.useFinalized)
|
return getBlock(ctx, logger, b.Connector, number, b.useFinalized, safe)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getBlock is a free function that can be called from other connectors to get a single block.
|
// getBlock is a free function that can be called from other connectors to get a single block.
|
||||||
func getBlock(ctx context.Context, logger *zap.Logger, conn Connector, number *big.Int, useFinalized bool) (*NewBlock, error) {
|
func getBlock(ctx context.Context, logger *zap.Logger, conn Connector, number *big.Int, useFinalized bool, safe bool) (*NewBlock, error) {
|
||||||
var numStr string
|
var numStr string
|
||||||
if number != nil {
|
if number != nil {
|
||||||
numStr = ethHexUtils.EncodeBig(number)
|
numStr = ethHexUtils.EncodeBig(number)
|
||||||
} else if useFinalized {
|
} else if useFinalized {
|
||||||
|
if safe {
|
||||||
|
numStr = "safe"
|
||||||
|
} else {
|
||||||
numStr = "finalized"
|
numStr = "finalized"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
numStr = "latest"
|
numStr = "latest"
|
||||||
}
|
}
|
||||||
|
@ -213,5 +243,6 @@ func getBlock(ctx context.Context, logger *zap.Logger, conn Connector, number *b
|
||||||
Number: &n,
|
Number: &n,
|
||||||
Hash: m.Hash,
|
Hash: m.Hash,
|
||||||
L1BlockNumber: l1bn,
|
L1BlockNumber: l1bn,
|
||||||
|
Safe: safe,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ func (c *PolygonConnector) postBlock(ctx context.Context, blockNum *big.Int, sin
|
||||||
return fmt.Errorf("blockNum is nil")
|
return fmt.Errorf("blockNum is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err := getBlock(ctx, c.logger, c.Connector, blockNum, false)
|
block, err := getBlock(ctx, c.logger, c.Connector, blockNum, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get block %s: %w", blockNum.String(), err)
|
return fmt.Errorf("failed to get block %s: %w", blockNum.String(), err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,8 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
timeout, cancel := context.WithTimeout(ctx, 15*time.Second)
|
timeout, cancel := context.WithTimeout(ctx, 15*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
safeBlocksSupported := false
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if w.chainID == vaa.ChainIDCelo && !w.unsafeDevMode {
|
if w.chainID == vaa.ChainIDCelo && !w.unsafeDevMode {
|
||||||
// When we are running in mainnet or testnet, we need to use the Celo ethereum library rather than go-ethereum.
|
// When we are running in mainnet or testnet, we need to use the Celo ethereum library rather than go-ethereum.
|
||||||
|
@ -197,14 +199,20 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
return fmt.Errorf("dialing eth client failed: %w", err)
|
return fmt.Errorf("dialing eth client failed: %w", err)
|
||||||
}
|
}
|
||||||
} else if useFinalizedBlocks {
|
} else if useFinalizedBlocks {
|
||||||
|
if w.chainID == vaa.ChainIDEthereum && !w.unsafeDevMode {
|
||||||
|
safeBlocksSupported = true
|
||||||
|
logger.Info("using finalized blocks, will publish safe blocks")
|
||||||
|
} else {
|
||||||
logger.Info("using finalized blocks")
|
logger.Info("using finalized blocks")
|
||||||
|
}
|
||||||
|
|
||||||
baseConnector, err := connectors.NewEthereumConnector(timeout, w.networkName, w.url, w.contract, logger)
|
baseConnector, err := connectors.NewEthereumConnector(timeout, w.networkName, w.url, w.contract, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
||||||
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
||||||
return fmt.Errorf("dialing eth client failed: %w", err)
|
return fmt.Errorf("dialing eth client failed: %w", err)
|
||||||
}
|
}
|
||||||
w.ethConn, err = connectors.NewBlockPollConnector(ctx, baseConnector, finalizers.NewDefaultFinalizer(), 250*time.Millisecond, true)
|
w.ethConn, err = connectors.NewBlockPollConnector(ctx, baseConnector, finalizers.NewDefaultFinalizer(), 250*time.Millisecond, true, safeBlocksSupported)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
||||||
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
||||||
|
@ -218,7 +226,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
return fmt.Errorf("dialing eth client failed: %w", err)
|
return fmt.Errorf("dialing eth client failed: %w", err)
|
||||||
}
|
}
|
||||||
finalizer := finalizers.NewMoonbeamFinalizer(logger, baseConnector)
|
finalizer := finalizers.NewMoonbeamFinalizer(logger, baseConnector)
|
||||||
w.ethConn, err = connectors.NewBlockPollConnector(ctx, baseConnector, finalizer, 250*time.Millisecond, false)
|
w.ethConn, err = connectors.NewBlockPollConnector(ctx, baseConnector, finalizer, 250*time.Millisecond, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
||||||
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
||||||
|
@ -235,7 +243,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
return fmt.Errorf("dialing eth client failed: %w", err)
|
return fmt.Errorf("dialing eth client failed: %w", err)
|
||||||
}
|
}
|
||||||
finalizer := finalizers.NewNeonFinalizer(logger, baseConnector, baseConnector.Client(), w.l1Finalizer)
|
finalizer := finalizers.NewNeonFinalizer(logger, baseConnector, baseConnector.Client(), w.l1Finalizer)
|
||||||
pollConnector, err := connectors.NewBlockPollConnector(ctx, baseConnector, finalizer, 250*time.Millisecond, false)
|
pollConnector, err := connectors.NewBlockPollConnector(ctx, baseConnector, finalizer, 250*time.Millisecond, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
||||||
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
||||||
|
@ -258,7 +266,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
return fmt.Errorf("dialing eth client failed: %w", err)
|
return fmt.Errorf("dialing eth client failed: %w", err)
|
||||||
}
|
}
|
||||||
finalizer := finalizers.NewArbitrumFinalizer(logger, baseConnector, baseConnector.Client(), w.l1Finalizer)
|
finalizer := finalizers.NewArbitrumFinalizer(logger, baseConnector, baseConnector.Client(), w.l1Finalizer)
|
||||||
pollConnector, err := connectors.NewBlockPollConnector(ctx, baseConnector, finalizer, 250*time.Millisecond, false)
|
pollConnector, err := connectors.NewBlockPollConnector(ctx, baseConnector, finalizer, 250*time.Millisecond, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
||||||
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
||||||
|
@ -281,7 +289,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
return fmt.Errorf("dialing eth client failed: %w", err)
|
return fmt.Errorf("dialing eth client failed: %w", err)
|
||||||
}
|
}
|
||||||
finalizer := finalizers.NewOptimismFinalizer(timeout, logger, baseConnector, w.l1Finalizer)
|
finalizer := finalizers.NewOptimismFinalizer(timeout, logger, baseConnector, w.l1Finalizer)
|
||||||
w.ethConn, err = connectors.NewBlockPollConnector(ctx, baseConnector, finalizer, 250*time.Millisecond, false)
|
w.ethConn, err = connectors.NewBlockPollConnector(ctx, baseConnector, finalizer, 250*time.Millisecond, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
||||||
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
||||||
|
@ -348,9 +356,10 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Track the current block number so we can compare it to the block number of
|
// Track the current block numbers so we can compare it to the block number of
|
||||||
// the message publication for observation requests.
|
// the message publication for observation requests.
|
||||||
var currentBlockNumber uint64
|
var currentBlockNumber uint64
|
||||||
|
var currentSafeBlockNumber uint64
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
@ -377,11 +386,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
// always sends the head before it sends the logs (implicit synchronization
|
// always sends the head before it sends the logs (implicit synchronization
|
||||||
// by relying on the same websocket connection).
|
// by relying on the same websocket connection).
|
||||||
blockNumberU := atomic.LoadUint64(¤tBlockNumber)
|
blockNumberU := atomic.LoadUint64(¤tBlockNumber)
|
||||||
if blockNumberU == 0 {
|
safeBlockNumberU := atomic.LoadUint64(¤tSafeBlockNumber)
|
||||||
logger.Error("no block number available, ignoring observation request",
|
|
||||||
zap.String("eth_network", w.networkName))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout, cancel := context.WithTimeout(ctx, 5*time.Second)
|
timeout, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
blockNumber, msgs, err := MessageEventsForTransaction(timeout, w.ethConn, w.contract, w.chainID, tx)
|
blockNumber, msgs, err := MessageEventsForTransaction(timeout, w.ethConn, w.contract, w.chainID, tx)
|
||||||
|
@ -407,6 +412,43 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if msg.ConsistencyLevel == vaa.ConsistencyLevelSafe && safeBlocksSupported {
|
||||||
|
if safeBlockNumberU == 0 {
|
||||||
|
logger.Error("no safe block number available, ignoring observation request",
|
||||||
|
zap.String("eth_network", w.networkName))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if blockNumber <= safeBlockNumberU {
|
||||||
|
logger.Info("re-observed message publication transaction",
|
||||||
|
zap.Stringer("tx", msg.TxHash),
|
||||||
|
zap.Stringer("emitter_address", msg.EmitterAddress),
|
||||||
|
zap.Uint64("sequence", msg.Sequence),
|
||||||
|
zap.Uint64("current_safe_block", safeBlockNumberU),
|
||||||
|
zap.Uint64("observed_block", blockNumber),
|
||||||
|
zap.String("eth_network", w.networkName),
|
||||||
|
)
|
||||||
|
w.msgChan <- msg
|
||||||
|
} else {
|
||||||
|
logger.Info("ignoring re-observed message publication transaction",
|
||||||
|
zap.Stringer("tx", msg.TxHash),
|
||||||
|
zap.Stringer("emitter_address", msg.EmitterAddress),
|
||||||
|
zap.Uint64("sequence", msg.Sequence),
|
||||||
|
zap.Uint64("current_safe_block", safeBlockNumberU),
|
||||||
|
zap.Uint64("observed_block", blockNumber),
|
||||||
|
zap.String("eth_network", w.networkName),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if blockNumberU == 0 {
|
||||||
|
logger.Error("no block number available, ignoring observation request",
|
||||||
|
zap.String("eth_network", w.networkName))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var expectedConfirmations uint64
|
var expectedConfirmations uint64
|
||||||
if w.waitForConfirmations {
|
if w.waitForConfirmations {
|
||||||
expectedConfirmations = uint64(msg.ConsistencyLevel)
|
expectedConfirmations = uint64(msg.ConsistencyLevel)
|
||||||
|
@ -554,7 +596,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ev.Number == nil {
|
if ev.Number == nil {
|
||||||
logger.Error("new header block number is nil", zap.String("eth_network", w.networkName))
|
logger.Error("new header block number is nil", zap.String("eth_network", w.networkName), zap.Bool("is_safe_block", ev.Safe))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,6 +605,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
logger.Info("processing new header",
|
logger.Info("processing new header",
|
||||||
zap.Stringer("current_block", ev.Number),
|
zap.Stringer("current_block", ev.Number),
|
||||||
zap.Stringer("current_blockhash", currentHash),
|
zap.Stringer("current_blockhash", currentHash),
|
||||||
|
zap.Bool("is_safe_block", ev.Safe),
|
||||||
zap.String("eth_network", w.networkName))
|
zap.String("eth_network", w.networkName))
|
||||||
currentEthHeight.WithLabelValues(w.networkName).Set(float64(ev.Number.Int64()))
|
currentEthHeight.WithLabelValues(w.networkName).Set(float64(ev.Number.Int64()))
|
||||||
readiness.SetReady(w.readiness)
|
readiness.SetReady(w.readiness)
|
||||||
|
@ -574,12 +617,24 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
w.pendingMu.Lock()
|
w.pendingMu.Lock()
|
||||||
|
|
||||||
blockNumberU := ev.Number.Uint64()
|
blockNumberU := ev.Number.Uint64()
|
||||||
|
if ev.Safe {
|
||||||
|
atomic.StoreUint64(¤tSafeBlockNumber, blockNumberU)
|
||||||
|
} else {
|
||||||
atomic.StoreUint64(¤tBlockNumber, blockNumberU)
|
atomic.StoreUint64(¤tBlockNumber, blockNumberU)
|
||||||
atomic.StoreUint64(&w.latestFinalizedBlockNumber, blockNumberU)
|
atomic.StoreUint64(&w.latestFinalizedBlockNumber, blockNumberU)
|
||||||
|
}
|
||||||
|
|
||||||
for key, pLock := range w.pending {
|
for key, pLock := range w.pending {
|
||||||
|
// If this block is safe, only process messages wanting safe.
|
||||||
|
// If it's not safe, only process messages wanting finalized.
|
||||||
|
if safeBlocksSupported {
|
||||||
|
if ev.Safe != (pLock.message.ConsistencyLevel == vaa.ConsistencyLevelSafe) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var expectedConfirmations uint64
|
var expectedConfirmations uint64
|
||||||
if w.waitForConfirmations {
|
if w.waitForConfirmations && !ev.Safe {
|
||||||
expectedConfirmations = uint64(pLock.message.ConsistencyLevel)
|
expectedConfirmations = uint64(pLock.message.ConsistencyLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,6 +646,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
zap.Stringer("emitter_address", key.EmitterAddress),
|
zap.Stringer("emitter_address", key.EmitterAddress),
|
||||||
zap.Uint64("sequence", key.Sequence),
|
zap.Uint64("sequence", key.Sequence),
|
||||||
zap.Stringer("current_block", ev.Number),
|
zap.Stringer("current_block", ev.Number),
|
||||||
|
zap.Bool("is_safe_block", ev.Safe),
|
||||||
zap.Stringer("current_blockhash", currentHash),
|
zap.Stringer("current_blockhash", currentHash),
|
||||||
zap.String("eth_network", w.networkName),
|
zap.String("eth_network", w.networkName),
|
||||||
zap.Uint64("expectedConfirmations", expectedConfirmations),
|
zap.Uint64("expectedConfirmations", expectedConfirmations),
|
||||||
|
@ -622,6 +678,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
zap.Stringer("emitter_address", key.EmitterAddress),
|
zap.Stringer("emitter_address", key.EmitterAddress),
|
||||||
zap.Uint64("sequence", key.Sequence),
|
zap.Uint64("sequence", key.Sequence),
|
||||||
zap.Stringer("current_block", ev.Number),
|
zap.Stringer("current_block", ev.Number),
|
||||||
|
zap.Bool("is_safe_block", ev.Safe),
|
||||||
zap.Stringer("current_blockhash", currentHash),
|
zap.Stringer("current_blockhash", currentHash),
|
||||||
zap.String("eth_network", w.networkName),
|
zap.String("eth_network", w.networkName),
|
||||||
zap.Error(err))
|
zap.Error(err))
|
||||||
|
@ -640,6 +697,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
zap.Stringer("emitter_address", key.EmitterAddress),
|
zap.Stringer("emitter_address", key.EmitterAddress),
|
||||||
zap.Uint64("sequence", key.Sequence),
|
zap.Uint64("sequence", key.Sequence),
|
||||||
zap.Stringer("current_block", ev.Number),
|
zap.Stringer("current_block", ev.Number),
|
||||||
|
zap.Bool("is_safe_block", ev.Safe),
|
||||||
zap.Stringer("current_blockhash", currentHash),
|
zap.Stringer("current_blockhash", currentHash),
|
||||||
zap.String("eth_network", w.networkName),
|
zap.String("eth_network", w.networkName),
|
||||||
zap.Error(err))
|
zap.Error(err))
|
||||||
|
@ -656,6 +714,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
zap.Stringer("emitter_address", key.EmitterAddress),
|
zap.Stringer("emitter_address", key.EmitterAddress),
|
||||||
zap.Uint64("sequence", key.Sequence),
|
zap.Uint64("sequence", key.Sequence),
|
||||||
zap.Stringer("current_block", ev.Number),
|
zap.Stringer("current_block", ev.Number),
|
||||||
|
zap.Bool("is_safe_block", ev.Safe),
|
||||||
zap.Stringer("current_blockhash", currentHash),
|
zap.Stringer("current_blockhash", currentHash),
|
||||||
zap.String("eth_network", w.networkName),
|
zap.String("eth_network", w.networkName),
|
||||||
zap.Error(err))
|
zap.Error(err))
|
||||||
|
@ -672,6 +731,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
zap.Stringer("emitter_address", key.EmitterAddress),
|
zap.Stringer("emitter_address", key.EmitterAddress),
|
||||||
zap.Uint64("sequence", key.Sequence),
|
zap.Uint64("sequence", key.Sequence),
|
||||||
zap.Stringer("current_block", ev.Number),
|
zap.Stringer("current_block", ev.Number),
|
||||||
|
zap.Bool("is_safe_block", ev.Safe),
|
||||||
zap.Stringer("current_blockhash", currentHash),
|
zap.Stringer("current_blockhash", currentHash),
|
||||||
zap.String("eth_network", w.networkName))
|
zap.String("eth_network", w.networkName))
|
||||||
delete(w.pending, key)
|
delete(w.pending, key)
|
||||||
|
@ -685,6 +745,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
zap.Stringer("emitter_address", key.EmitterAddress),
|
zap.Stringer("emitter_address", key.EmitterAddress),
|
||||||
zap.Uint64("sequence", key.Sequence),
|
zap.Uint64("sequence", key.Sequence),
|
||||||
zap.Stringer("current_block", ev.Number),
|
zap.Stringer("current_block", ev.Number),
|
||||||
|
zap.Bool("is_safe_block", ev.Safe),
|
||||||
zap.Stringer("current_blockhash", currentHash),
|
zap.Stringer("current_blockhash", currentHash),
|
||||||
zap.String("eth_network", w.networkName))
|
zap.String("eth_network", w.networkName))
|
||||||
delete(w.pending, key)
|
delete(w.pending, key)
|
||||||
|
@ -696,6 +757,7 @@ func (w *Watcher) Run(ctx context.Context) error {
|
||||||
w.pendingMu.Unlock()
|
w.pendingMu.Unlock()
|
||||||
logger.Info("processed new header",
|
logger.Info("processed new header",
|
||||||
zap.Stringer("current_block", ev.Number),
|
zap.Stringer("current_block", ev.Number),
|
||||||
|
zap.Bool("is_safe_block", ev.Safe),
|
||||||
zap.Stringer("current_blockhash", currentHash),
|
zap.Stringer("current_blockhash", currentHash),
|
||||||
zap.Duration("took", time.Since(start)),
|
zap.Duration("took", time.Since(start)),
|
||||||
zap.String("eth_network", w.networkName))
|
zap.String("eth_network", w.networkName))
|
||||||
|
|
|
@ -116,6 +116,7 @@ type (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ConsistencyLevelPublishImmediately = uint8(200)
|
ConsistencyLevelPublishImmediately = uint8(200)
|
||||||
|
ConsistencyLevelSafe = uint8(201)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a Address) MarshalJSON() ([]byte, error) {
|
func (a Address) MarshalJSON() ([]byte, error) {
|
||||||
|
|
Loading…
Reference in New Issue