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  }