code.vegaprotocol.io/vega@v0.79.0/core/datasource/external/ethverifier/acked_events.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 ethverifier
    17  
    18  import (
    19  	"github.com/emirpasic/gods/sets/treeset"
    20  	"github.com/emirpasic/gods/utils"
    21  )
    22  
    23  const oneHour = 3600 // seconds
    24  
    25  type ackedEvtBucket struct {
    26  	ts     int64
    27  	endTs  int64
    28  	hashes map[string]struct{}
    29  }
    30  
    31  func ackedEvtBucketComparator(a, b interface{}) int {
    32  	bucket1 := a.(*ackedEvtBucket)
    33  	bucket2 := b.(*ackedEvtBucket)
    34  	return utils.Int64Comparator(bucket1.ts, bucket2.ts)
    35  }
    36  
    37  type ackedEvents struct {
    38  	timeService TimeService
    39  	events      *treeset.Set // we only care about the key
    40  }
    41  
    42  func (a *ackedEvents) AddAt(ts int64, hashes ...string) {
    43  	_, value := a.events.Find(func(i int, value interface{}) bool {
    44  		bucket := value.(*ackedEvtBucket)
    45  		return bucket.ts <= ts && bucket.endTs >= ts
    46  	})
    47  
    48  	if value != nil {
    49  		bucket := value.(*ackedEvtBucket)
    50  		for _, newHash := range hashes {
    51  			bucket.hashes[newHash] = struct{}{}
    52  		}
    53  
    54  		return
    55  	}
    56  
    57  	hashesM := map[string]struct{}{}
    58  	for _, v := range hashes {
    59  		hashesM[v] = struct{}{}
    60  	}
    61  
    62  	a.events.Add(&ackedEvtBucket{ts: ts, endTs: ts + oneHour, hashes: hashesM})
    63  }
    64  
    65  // RestoreExactAt - is to be used when loading a snapshot only
    66  // this prevent restoring in different buckets, which could happen
    67  // when events are received out of sync (e.g: timestamps 100 before 90) which could make gap between buckets.
    68  func (a *ackedEvents) RestoreExactAt(ts int64, hashes ...string) {
    69  	hashesM := map[string]struct{}{}
    70  	for _, v := range hashes {
    71  		hashesM[v] = struct{}{}
    72  	}
    73  
    74  	a.events.Add(&ackedEvtBucket{ts: ts, endTs: ts + oneHour, hashes: hashesM})
    75  }
    76  
    77  func (a *ackedEvents) Add(hash string) {
    78  	a.AddAt(a.timeService.GetTimeNow().Unix(), hash)
    79  }
    80  
    81  func (a *ackedEvents) Contains(hash string) bool {
    82  	_, value := a.events.Find(func(index int, value interface{}) bool {
    83  		bucket := value.(*ackedEvtBucket)
    84  		_, ok := bucket.hashes[hash]
    85  		return ok
    86  	})
    87  
    88  	return value != nil
    89  }
    90  
    91  func (a *ackedEvents) RemoveBefore(ts int64) {
    92  	set := a.events.Select(func(index int, value interface{}) bool {
    93  		bucket := value.(*ackedEvtBucket)
    94  		return bucket.ts <= ts
    95  	})
    96  
    97  	a.events.Remove(set.Values()...)
    98  }
    99  
   100  func (a *ackedEvents) Size() int {
   101  	return a.events.Size()
   102  }