github.com/amazechain/amc@v0.1.3/modules/changeset/changeset.go (about) 1 // Copyright 2023 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The AmazeChain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package changeset 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "fmt" 23 "github.com/amazechain/amc/common/types" 24 "github.com/amazechain/amc/modules" 25 "github.com/amazechain/amc/modules/ethdb" 26 "math" 27 "reflect" 28 29 "github.com/ledgerwatch/erigon-lib/kv" 30 ) 31 32 func NewChangeSet() *ChangeSet { 33 return &ChangeSet{ 34 Changes: make([]Change, 0), 35 } 36 } 37 38 type Change struct { 39 Key []byte 40 Value []byte 41 } 42 43 // ChangeSet is a map with keys of the same size. 44 // Both keys and values are byte strings. 45 type ChangeSet struct { 46 // Invariant: all keys are of the same size. 47 Changes []Change 48 keyLen int 49 } 50 51 // BEGIN sort.Interface 52 53 func (s *ChangeSet) Len() int { 54 return len(s.Changes) 55 } 56 57 func (s *ChangeSet) Swap(i, j int) { 58 s.Changes[i], s.Changes[j] = s.Changes[j], s.Changes[i] 59 } 60 61 func (s *ChangeSet) Less(i, j int) bool { 62 cmp := bytes.Compare(s.Changes[i].Key, s.Changes[j].Key) 63 if cmp == 0 { 64 cmp = bytes.Compare(s.Changes[i].Value, s.Changes[j].Value) 65 } 66 return cmp < 0 67 } 68 69 // END sort.Interface 70 func (s *ChangeSet) KeySize() int { 71 if s.keyLen != 0 { 72 return s.keyLen 73 } 74 for _, c := range s.Changes { 75 return len(c.Key) 76 } 77 return 0 78 } 79 80 func (s *ChangeSet) checkKeySize(key []byte) error { 81 if (s.Len() == 0 && s.KeySize() == 0) || (len(key) == s.KeySize() && len(key) > 0) { 82 return nil 83 } 84 85 return fmt.Errorf("wrong key size in AccountChangeSet: expected %d, actual %d", s.KeySize(), len(key)) 86 } 87 88 // Add adds a new entry to the AccountChangeSet. 89 // One must not add an existing key 90 // and may add keys only of the same size. 91 func (s *ChangeSet) Add(key []byte, value []byte) error { 92 if err := s.checkKeySize(key); err != nil { 93 return err 94 } 95 96 s.Changes = append(s.Changes, Change{ 97 Key: key, 98 Value: value, 99 }) 100 return nil 101 } 102 103 func (s *ChangeSet) ChangedKeys() map[string]struct{} { 104 m := make(map[string]struct{}, len(s.Changes)) 105 for i := range s.Changes { 106 m[string(s.Changes[i].Key)] = struct{}{} 107 } 108 return m 109 } 110 111 func (s *ChangeSet) Equals(s2 *ChangeSet) bool { 112 return reflect.DeepEqual(s.Changes, s2.Changes) 113 } 114 115 func (s *ChangeSet) String() string { 116 str := "" 117 for _, v := range s.Changes { 118 str += fmt.Sprintf("%v %s : %s\n", len(v.Key), types.Bytes2Hex(v.Key), string(v.Value)) 119 } 120 return str 121 } 122 123 // Encoded Method 124 func FromDBFormat(dbKey, dbValue []byte) (uint64, []byte, []byte, error) { 125 if len(dbKey) == 8 { 126 return DecodeAccounts(dbKey, dbValue) 127 } else { 128 return DecodeStorage(dbKey, dbValue) 129 } 130 } 131 132 func AvailableFrom(tx kv.Tx) (uint64, error) { 133 c, err := tx.Cursor(modules.AccountChangeSet) 134 if err != nil { 135 return math.MaxUint64, err 136 } 137 defer c.Close() 138 k, _, err := c.First() 139 if err != nil { 140 return math.MaxUint64, err 141 } 142 if len(k) == 0 { 143 return math.MaxUint64, nil 144 } 145 return binary.BigEndian.Uint64(k), nil 146 } 147 func AvailableStorageFrom(tx kv.Tx) (uint64, error) { 148 c, err := tx.Cursor(modules.StorageChangeSet) 149 if err != nil { 150 return math.MaxUint64, err 151 } 152 defer c.Close() 153 k, _, err := c.First() 154 if err != nil { 155 return math.MaxUint64, err 156 } 157 if len(k) == 0 { 158 return math.MaxUint64, nil 159 } 160 return binary.BigEndian.Uint64(k), nil 161 } 162 163 // [from:to) 164 func ForRange(db kv.Tx, bucket string, from, to uint64, walker func(blockN uint64, k, v []byte) error) error { 165 var blockN uint64 166 c, err := db.Cursor(bucket) 167 if err != nil { 168 return err 169 } 170 defer c.Close() 171 return ethdb.Walk(c, modules.EncodeBlockNumber(from), 0, func(k, v []byte) (bool, error) { 172 var err error 173 blockN, k, v, err = FromDBFormat(k, v) 174 if err != nil { 175 return false, err 176 } 177 if blockN >= to { 178 return false, nil 179 } 180 if err = walker(blockN, k, v); err != nil { 181 return false, err 182 } 183 return true, nil 184 }) 185 } 186 func ForEach(db kv.Tx, bucket string, startkey []byte, walker func(blockN uint64, k, v []byte) error) error { 187 var blockN uint64 188 return db.ForEach(bucket, startkey, func(k, v []byte) error { 189 var err error 190 blockN, k, v, err = FromDBFormat(k, v) 191 if err != nil { 192 return err 193 } 194 return walker(blockN, k, v) 195 }) 196 } 197 func ForPrefix(db kv.Tx, bucket string, startkey []byte, walker func(blockN uint64, k, v []byte) error) error { 198 var blockN uint64 199 return db.ForPrefix(bucket, startkey, func(k, v []byte) error { 200 var err error 201 blockN, k, v, err = FromDBFormat(k, v) 202 if err != nil { 203 return err 204 } 205 return walker(blockN, k, v) 206 }) 207 } 208 209 func Truncate(tx kv.RwTx, from uint64) error { 210 keyStart := modules.EncodeBlockNumber(from) 211 212 { 213 c, err := tx.RwCursorDupSort(modules.AccountChangeSet) 214 if err != nil { 215 return err 216 } 217 defer c.Close() 218 for k, _, err := c.Seek(keyStart); k != nil; k, _, err = c.NextNoDup() { 219 if err != nil { 220 return err 221 } 222 err = c.DeleteCurrentDuplicates() 223 if err != nil { 224 return err 225 } 226 } 227 } 228 { 229 c, err := tx.RwCursorDupSort(modules.StorageChangeSet) 230 if err != nil { 231 return err 232 } 233 defer c.Close() 234 for k, _, err := c.Seek(keyStart); k != nil; k, _, err = c.NextNoDup() { 235 if err != nil { 236 return err 237 } 238 err = c.DeleteCurrentDuplicates() 239 if err != nil { 240 return err 241 } 242 } 243 } 244 return nil 245 } 246 247 var Mapper = map[string]struct { 248 IndexBucket string 249 IndexChunkKey func([]byte, uint64) []byte 250 Find func(cursor kv.CursorDupSort, blockNumber uint64, key []byte) ([]byte, error) 251 New func() *ChangeSet 252 Encode Encoder 253 Decode Decoder 254 }{ 255 modules.AccountChangeSet: { 256 IndexBucket: modules.AccountsHistory, 257 IndexChunkKey: modules.AccountIndexChunkKey, 258 New: NewAccountChangeSet, 259 Find: FindAccount, 260 Encode: EncodeAccounts, 261 Decode: DecodeAccounts, 262 }, 263 modules.StorageChangeSet: { 264 IndexBucket: modules.StorageHistory, 265 IndexChunkKey: modules.StorageIndexChunkKey, 266 Find: FindStorage, 267 New: NewStorageChangeSet, 268 Encode: EncodeStorage, 269 Decode: DecodeStorage, 270 }, 271 }