github.com/amazechain/amc@v0.1.3/modules/state/change_set_writer.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 state 18 19 import ( 20 "fmt" 21 "github.com/amazechain/amc/common/account" 22 "github.com/amazechain/amc/modules/changeset" 23 24 "github.com/amazechain/amc/common/hexutil" 25 "github.com/amazechain/amc/common/types" 26 "github.com/amazechain/amc/internal/avm/common" 27 "github.com/amazechain/amc/modules" 28 "github.com/holiman/uint256" 29 "github.com/ledgerwatch/erigon-lib/kv" 30 ) 31 32 // ChangeSetWriter is a mock StateWriter that accumulates changes in-memory into ChangeSets. 33 type ChangeSetWriter struct { 34 db kv.RwTx 35 accountChanges map[types.Address][]byte 36 storageChanged map[types.Address]bool 37 storageChanges map[string][]byte 38 blockNumber uint64 39 } 40 41 func NewChangeSetWriter() *ChangeSetWriter { 42 return &ChangeSetWriter{ 43 accountChanges: make(map[types.Address][]byte), 44 storageChanged: make(map[types.Address]bool), 45 storageChanges: make(map[string][]byte), 46 } 47 } 48 func NewChangeSetWriterPlain(db kv.RwTx, blockNumber uint64) *ChangeSetWriter { 49 return &ChangeSetWriter{ 50 db: db, 51 accountChanges: make(map[types.Address][]byte), 52 storageChanged: make(map[types.Address]bool), 53 storageChanges: make(map[string][]byte), 54 blockNumber: blockNumber, 55 } 56 } 57 58 func (w *ChangeSetWriter) GetAccountChanges() (*changeset.ChangeSet, error) { 59 cs := changeset.NewAccountChangeSet() 60 for address, val := range w.accountChanges { 61 if err := cs.Add(common.CopyBytes(address[:]), val); err != nil { 62 return nil, err 63 } 64 } 65 return cs, nil 66 } 67 func (w *ChangeSetWriter) GetStorageChanges() (*changeset.ChangeSet, error) { 68 cs := changeset.NewStorageChangeSet() 69 for key, val := range w.storageChanges { 70 if err := cs.Add([]byte(key), val); err != nil { 71 return nil, err 72 } 73 } 74 return cs, nil 75 } 76 77 func accountsEqual(a1, a2 *account.StateAccount) bool { 78 if a1.Nonce != a2.Nonce { 79 return false 80 } 81 if !a1.Initialised { 82 if a2.Initialised { 83 return false 84 } 85 } else if !a2.Initialised { 86 return false 87 } else if a1.Balance.Cmp(&a2.Balance) != 0 { 88 return false 89 } 90 if a1.IsEmptyCodeHash() { 91 if !a2.IsEmptyCodeHash() { 92 return false 93 } 94 } else if a2.IsEmptyCodeHash() { 95 return false 96 } else if a1.CodeHash != a2.CodeHash { 97 return false 98 } 99 return true 100 } 101 102 func (w *ChangeSetWriter) UpdateAccountData(address types.Address, original, account *account.StateAccount) error { 103 //fmt.Printf("balance,%x,%d\n", address, &account.Balance) 104 if !accountsEqual(original, account) || w.storageChanged[address] { 105 w.accountChanges[address] = originalAccountData(original, true /*omitHashes*/) 106 } 107 return nil 108 } 109 110 func (w *ChangeSetWriter) UpdateAccountCode(address types.Address, incarnation uint16, codeHash types.Hash, code []byte) error { 111 //fmt.Printf("code,%x,%x\n", address, code) 112 return nil 113 } 114 115 func (w *ChangeSetWriter) DeleteAccount(address types.Address, original *account.StateAccount) error { 116 //fmt.Printf("delete,%x\n", address) 117 if original == nil || !original.Initialised { 118 return nil 119 } 120 w.accountChanges[address] = originalAccountData(original, false) 121 return nil 122 } 123 124 func (w *ChangeSetWriter) WriteAccountStorage(address types.Address, incarnation uint16, key *types.Hash, original, value *uint256.Int) error { 125 //fmt.Printf("storage,%x,%x,%x\n", address, *key, value.Bytes()) 126 if *original == *value { 127 return nil 128 } 129 130 compositeKey := modules.PlainGenerateCompositeStorageKey(address.Bytes(), incarnation, key.Bytes()) 131 132 w.storageChanges[string(compositeKey)] = original.Bytes() 133 w.storageChanged[address] = true 134 135 return nil 136 } 137 138 func (w *ChangeSetWriter) CreateContract(address types.Address) error { 139 return nil 140 } 141 142 func (w *ChangeSetWriter) WriteChangeSets() error { 143 //if w.blockNumber == 547600 { 144 // changeset.Truncate(w.db, 547600) 145 //} 146 accountChanges, err := w.GetAccountChanges() 147 if err != nil { 148 return err 149 } 150 if err = changeset.Mapper[modules.AccountChangeSet].Encode(w.blockNumber, accountChanges, func(k, v []byte) error { 151 if err = w.db.AppendDup(modules.AccountChangeSet, k, v); err != nil { 152 return err 153 } 154 return nil 155 }); err != nil { 156 return err 157 } 158 159 storageChanges, err := w.GetStorageChanges() 160 if err != nil { 161 return err 162 } 163 if storageChanges.Len() == 0 { 164 return nil 165 } 166 if err = changeset.Mapper[modules.StorageChangeSet].Encode(w.blockNumber, storageChanges, func(k, v []byte) error { 167 if err = w.db.AppendDup(modules.StorageChangeSet, k, v); err != nil { 168 return err 169 } 170 return nil 171 }); err != nil { 172 return err 173 } 174 return nil 175 } 176 177 func (w *ChangeSetWriter) WriteHistory() error { 178 accountChanges, err := w.GetAccountChanges() 179 if err != nil { 180 return err 181 } 182 err = writeIndex(w.blockNumber, accountChanges, modules.AccountsHistory, w.db) 183 if err != nil { 184 return err 185 } 186 187 storageChanges, err := w.GetStorageChanges() 188 if err != nil { 189 return err 190 } 191 err = writeIndex(w.blockNumber, storageChanges, modules.StorageHistory, w.db) 192 if err != nil { 193 return err 194 } 195 196 return nil 197 } 198 199 func (w *ChangeSetWriter) PrintChangedAccounts() { 200 fmt.Println("Account Changes") 201 for k := range w.accountChanges { 202 fmt.Println(hexutil.Encode(k.Bytes())) 203 } 204 fmt.Println("------------------------------------------") 205 }