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 }