mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-08 12:01:20 +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.1 KiB
Go
120 lines
3.1 KiB
Go
package stateless
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"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/consensus/ethash"
|
|
"github.com/ledgerwatch/turbo-geth/core"
|
|
"github.com/ledgerwatch/turbo-geth/core/state"
|
|
"github.com/ledgerwatch/turbo-geth/core/vm"
|
|
"github.com/ledgerwatch/turbo-geth/ethdb"
|
|
"github.com/ledgerwatch/turbo-geth/params"
|
|
)
|
|
|
|
// CheckChangeSets re-executes historical transactions in read-only mode
|
|
// and checks that their outputs match the database ChangeSets.
|
|
func CheckChangeSets(blockNum uint64, chaindata string) error {
|
|
startTime := time.Now()
|
|
sigs := make(chan os.Signal, 1)
|
|
interruptCh := make(chan bool, 1)
|
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
go func() {
|
|
<-sigs
|
|
interruptCh <- true
|
|
}()
|
|
|
|
ethDb, err := ethdb.NewBoltDatabase(chaindata)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer ethDb.Close()
|
|
|
|
chainConfig := params.MainnetChainConfig
|
|
engine := ethash.NewFaker()
|
|
vmConfig := vm.Config{}
|
|
bc, err := core.NewBlockChain(ethDb, nil, chainConfig, engine, vmConfig, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
noOpWriter := state.NewNoopWriter()
|
|
|
|
interrupt := false
|
|
for !interrupt {
|
|
block := bc.GetBlockByNumber(blockNum)
|
|
if block == nil {
|
|
break
|
|
}
|
|
|
|
dbstate := state.NewDbState(ethDb, block.NumberU64()-1)
|
|
intraBlockState := state.New(dbstate)
|
|
csw := state.NewChangeSetWriter()
|
|
|
|
if err := runBlock(intraBlockState, noOpWriter, csw, chainConfig, bc, block); err != nil {
|
|
return err
|
|
}
|
|
|
|
expectedAccountChanges, err := changeset.EncodeChangeSet(csw.GetAccountChanges())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
dbAccountChanges, err := ethDb.GetChangeSetByBlock(dbutils.AccountsHistoryBucket, blockNum)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !bytes.Equal(dbAccountChanges, expectedAccountChanges) {
|
|
fmt.Printf("Unexpected account changes in block %d\n%s\nvs\n%s\n", blockNum, hexutil.Encode(dbAccountChanges), hexutil.Encode(expectedAccountChanges))
|
|
csw.PrintChangedAccounts()
|
|
return nil
|
|
}
|
|
|
|
expectedStorageChanges := csw.GetStorageChanges()
|
|
expectedtorageSerialized := make([]byte, 0)
|
|
if expectedStorageChanges.Len() > 0 {
|
|
expectedtorageSerialized, err = changeset.EncodeChangeSet(expectedStorageChanges)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
dbStorageChanges, err := ethDb.GetChangeSetByBlock(dbutils.StorageHistoryBucket, blockNum)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !bytes.Equal(dbStorageChanges, expectedtorageSerialized) {
|
|
fmt.Printf("Unexpected storage changes in block %d\n%s\nvs\n%s\n", blockNum, hexutil.Encode(dbStorageChanges), hexutil.Encode(expectedtorageSerialized))
|
|
return nil
|
|
}
|
|
|
|
blockNum++
|
|
if blockNum%1000 == 0 {
|
|
fmt.Printf("Checked %d blocks\n", blockNum)
|
|
}
|
|
|
|
// Check for interrupts
|
|
select {
|
|
case interrupt = <-interruptCh:
|
|
fmt.Println("interrupted, please wait for cleanup...")
|
|
default:
|
|
}
|
|
}
|
|
|
|
fmt.Printf("Checked %d blocks\n", blockNum)
|
|
fmt.Printf("Next time specify --block %d\n", blockNum)
|
|
fmt.Printf("CheckChangeSets took %s\n", time.Since(startTime))
|
|
|
|
return nil
|
|
}
|