mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-28 14:47:16 +00:00
aeed1657c7
* Clean up code duplication between IntraBlockState's FinalizeTx & CommitBlock * checkChangeSets command * linter * First attempt at checking account changes * Reuse runBlock in CheckChangeSets * linter * linter * Optionally include no-changes in the ChangeSets * linter * Detect storage changes for account change sets * Fix post-merge compilation errors * Use database format compatible with !debug.IsThinHistory() * PrintChangedAccounts in ChangeSetWriter * Avoid out-of-bounds access * Storage changes * hack FirstContractIncarnation * Call ChangeSetWriter only once per block
120 lines
3.2 KiB
Go
120 lines
3.2 KiB
Go
package state
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/ledgerwatch/turbo-geth/common"
|
|
"github.com/ledgerwatch/turbo-geth/common/changeset"
|
|
"github.com/ledgerwatch/turbo-geth/common/dbutils"
|
|
"github.com/ledgerwatch/turbo-geth/common/hexutil"
|
|
"github.com/ledgerwatch/turbo-geth/core/types/accounts"
|
|
"github.com/ledgerwatch/turbo-geth/crypto"
|
|
)
|
|
|
|
// ChangeSetWriter is a mock StateWriter that accumulates changes in-memory into ChangeSets.
|
|
type ChangeSetWriter struct {
|
|
accountChanges map[common.Address][]byte
|
|
storageChanged map[common.Address]bool
|
|
storageChanges map[string][]byte
|
|
}
|
|
|
|
func NewChangeSetWriter() *ChangeSetWriter {
|
|
return &ChangeSetWriter{
|
|
accountChanges: make(map[common.Address][]byte),
|
|
storageChanged: make(map[common.Address]bool),
|
|
storageChanges: make(map[string][]byte),
|
|
}
|
|
}
|
|
|
|
func (w *ChangeSetWriter) GetAccountChanges() *changeset.ChangeSet {
|
|
cs := changeset.NewAccountChangeSet()
|
|
for key, val := range w.accountChanges {
|
|
if err := cs.Add(crypto.Keccak256(key.Bytes()), val); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
return cs
|
|
}
|
|
|
|
func (w *ChangeSetWriter) GetStorageChanges() *changeset.ChangeSet {
|
|
cs := changeset.NewStorageChangeSet()
|
|
for key, val := range w.storageChanges {
|
|
if err := cs.Add([]byte(key), val); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
return cs
|
|
}
|
|
|
|
func accountData(original *accounts.Account) []byte {
|
|
var originalData []byte
|
|
if !original.Initialised {
|
|
originalData = []byte{}
|
|
} else {
|
|
originalDataLen := original.EncodingLengthForStorage()
|
|
originalData = make([]byte, originalDataLen)
|
|
original.EncodeForStorage(originalData)
|
|
}
|
|
return originalData
|
|
}
|
|
|
|
func (w *ChangeSetWriter) UpdateAccountData(ctx context.Context, address common.Address, original, account *accounts.Account) error {
|
|
if !accountsEqual(original, account) || w.storageChanged[address] {
|
|
w.accountChanges[address] = accountData(original)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *ChangeSetWriter) UpdateAccountCode(addrHash common.Hash, incarnation uint64, codeHash common.Hash, code []byte) error {
|
|
return nil
|
|
}
|
|
|
|
func (w *ChangeSetWriter) DeleteAccount(ctx context.Context, address common.Address, original *accounts.Account) error {
|
|
w.accountChanges[address] = accountData(original)
|
|
return nil
|
|
}
|
|
|
|
func (w *ChangeSetWriter) WriteAccountStorage(ctx context.Context, address common.Address, incarnation uint64, key, original, value *common.Hash) error {
|
|
if *original == *value {
|
|
return nil
|
|
}
|
|
|
|
secKey, err := common.HashData(key[:])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
addrHash, err := common.HashData(address[:])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if incarnation == 0 {
|
|
incarnation = FirstContractIncarnation
|
|
}
|
|
|
|
compositeKey := dbutils.GenerateCompositeStorageKey(addrHash, incarnation, secKey)
|
|
|
|
o := bytes.TrimLeft(original[:], "\x00")
|
|
originalValue := make([]byte, len(o))
|
|
copy(originalValue, o)
|
|
|
|
w.storageChanges[string(compositeKey)] = originalValue
|
|
w.storageChanged[address] = true
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w *ChangeSetWriter) CreateContract(address common.Address) error {
|
|
return nil
|
|
}
|
|
|
|
func (w *ChangeSetWriter) PrintChangedAccounts() {
|
|
fmt.Println("Account Changes")
|
|
for k := range w.accountChanges {
|
|
fmt.Println(hexutil.Encode(k.Bytes()))
|
|
}
|
|
fmt.Println("------------------------------------------")
|
|
}
|