diff --git a/les/checkpointoracle/oracle.go b/les/checkpointoracle/oracle.go index c3983e1a9..73bd8f35d 100644 --- a/les/checkpointoracle/oracle.go +++ b/les/checkpointoracle/oracle.go @@ -21,7 +21,9 @@ package checkpointoracle import ( "encoding/binary" + "sync" "sync/atomic" + "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -40,6 +42,11 @@ type CheckpointOracle struct { running int32 // Flag whether the contract backend is set or not getLocal func(uint64) params.TrustedCheckpoint // Function used to retrieve local checkpoint + + checkMu sync.Mutex // Mutex to sync access to the fields below + lastCheckTime time.Time // Time we last checked the checkpoint + lastCheckPoint *params.TrustedCheckpoint // The last stable checkpoint + lastCheckPointHeight uint64 // The height of last stable checkpoint } // New creates a checkpoint oracle handler with given configs and callback. @@ -88,6 +95,12 @@ func (oracle *CheckpointOracle) Contract() *checkpointoracle.CheckpointOracle { // StableCheckpoint returns the stable checkpoint which was generated by local // indexers and announced by trusted signers. func (oracle *CheckpointOracle) StableCheckpoint() (*params.TrustedCheckpoint, uint64) { + oracle.checkMu.Lock() + defer oracle.checkMu.Unlock() + if time.Since(oracle.lastCheckTime) < 1*time.Minute { + return oracle.lastCheckPoint, oracle.lastCheckPointHeight + } + // Look it up properly // Retrieve the latest checkpoint from the contract, abort if empty latest, hash, height, err := oracle.contract.Contract().GetLatestCheckpoint(nil) if err != nil || (latest == 0 && hash == [32]byte{}) { @@ -103,6 +116,9 @@ func (oracle *CheckpointOracle) StableCheckpoint() (*params.TrustedCheckpoint, u // // In both cases, no stable checkpoint will be returned. if local.HashEqual(hash) { + oracle.lastCheckTime = time.Now() + oracle.lastCheckPointHeight = height.Uint64() + oracle.lastCheckPoint = &local return &local, height.Uint64() } return nil, 0