2021-11-27 09:43:25 +00:00
package commands
import (
"bytes"
"context"
"errors"
"fmt"
2022-01-14 16:02:44 +00:00
"math/bits"
2021-11-27 09:43:25 +00:00
"os"
"os/signal"
"path"
2022-02-12 13:33:09 +00:00
"path/filepath"
2022-02-19 08:15:35 +00:00
"runtime"
2021-11-27 09:43:25 +00:00
"syscall"
2022-01-31 23:40:51 +00:00
"time"
2021-11-27 09:43:25 +00:00
2022-02-22 01:55:49 +00:00
metrics2 "github.com/VictoriaMetrics/metrics"
2021-11-27 09:43:25 +00:00
"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon-lib/aggregator"
2022-05-05 12:54:29 +00:00
"github.com/ledgerwatch/erigon-lib/commitment"
2022-01-31 23:40:51 +00:00
libcommon "github.com/ledgerwatch/erigon-lib/common"
2022-03-23 16:00:06 +00:00
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/mdbx"
2021-11-27 09:43:25 +00:00
kv2 "github.com/ledgerwatch/erigon-lib/kv/mdbx"
2022-04-28 05:42:14 +00:00
"github.com/ledgerwatch/erigon/eth/ethconsensusconfig"
2022-05-26 03:31:06 +00:00
"github.com/ledgerwatch/erigon/turbo/services"
2022-03-10 14:01:37 +00:00
"github.com/ledgerwatch/log/v3"
"github.com/spf13/cobra"
2021-11-27 09:43:25 +00:00
"github.com/ledgerwatch/erigon/common"
2022-03-17 07:30:47 +00:00
"github.com/ledgerwatch/erigon/consensus"
2022-01-14 16:02:44 +00:00
"github.com/ledgerwatch/erigon/consensus/ethash"
"github.com/ledgerwatch/erigon/consensus/misc"
2021-11-27 09:43:25 +00:00
"github.com/ledgerwatch/erigon/core"
"github.com/ledgerwatch/erigon/core/rawdb"
"github.com/ledgerwatch/erigon/core/state"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/core/types/accounts"
"github.com/ledgerwatch/erigon/core/vm"
2022-02-22 01:42:12 +00:00
"github.com/ledgerwatch/erigon/eth/ethconfig"
2021-11-27 09:43:25 +00:00
"github.com/ledgerwatch/erigon/params"
2022-02-22 01:42:12 +00:00
"github.com/ledgerwatch/erigon/turbo/snapshotsync"
2021-11-27 09:43:25 +00:00
)
2022-01-31 23:40:51 +00:00
const (
2022-03-23 16:00:06 +00:00
aggregationStep = 15625 /* this is 500'000 / 32 */
unwindLimit = 90000 /* how it is in geth */
logInterval = 30 * time . Second // time period to print aggregation stat to log
dirtySpaceThreshold = 2 * 1024 * 1024 * 1024 /* threshold of dirty space in MDBX transaction that triggers a commit */
2022-01-31 23:40:51 +00:00
)
2021-11-30 16:46:43 +00:00
var (
2022-01-16 21:24:54 +00:00
commitmentFrequency int // How many blocks to skip between calculating commitment
changesets bool
2022-02-12 00:06:57 +00:00
commitments bool
2022-05-05 12:54:29 +00:00
commitmentTrie string
2021-11-30 16:46:43 +00:00
)
2022-02-22 01:55:49 +00:00
var blockExecutionTimer = metrics2 . GetOrCreateSummary ( "chain_execution_seconds" )
2021-11-27 09:43:25 +00:00
func init ( ) {
withBlock ( erigon2Cmd )
2022-02-22 17:39:48 +00:00
withDataDir ( erigon2Cmd )
2022-02-22 01:42:12 +00:00
withSnapshotBlocks ( erigon2Cmd )
2022-03-10 14:01:37 +00:00
withChain ( erigon2Cmd )
2022-01-14 16:02:44 +00:00
erigon2Cmd . Flags ( ) . BoolVar ( & changesets , "changesets" , false , "set to true to generate changesets" )
2022-01-31 23:40:51 +00:00
erigon2Cmd . Flags ( ) . IntVar ( & commitmentFrequency , "commfreq" , 625 , "how many blocks to skip between calculating commitment" )
2022-02-12 00:06:57 +00:00
erigon2Cmd . Flags ( ) . BoolVar ( & commitments , "commitments" , false , "set to true to calculate commitments" )
2022-05-05 12:54:29 +00:00
erigon2Cmd . Flags ( ) . StringVar ( & commitmentTrie , "commitments.trie" , "hex" , "hex - use Hex Patricia Hashed Trie for commitments, bin - use of binary patricia trie" )
2022-02-14 23:15:24 +00:00
erigon2Cmd . Flags ( ) . IntVar ( & traceBlock , "traceblock" , 0 , "block number at which to turn on tracing" )
2021-11-27 09:43:25 +00:00
rootCmd . AddCommand ( erigon2Cmd )
}
var erigon2Cmd = & cobra . Command {
Use : "erigon2" ,
Short : "Exerimental command to re-execute blocks from beginning using erigon2 state representation" ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2022-01-31 23:40:51 +00:00
if commitmentFrequency < 1 || commitmentFrequency > aggregationStep {
return fmt . Errorf ( "commitmentFrequency cannot be less than 1 or more than %d: %d" , commitmentFrequency , aggregationStep )
2022-01-16 21:24:54 +00:00
}
2021-11-27 09:43:25 +00:00
logger := log . New ( )
2022-03-10 14:01:37 +00:00
return Erigon2 ( genesis , chainConfig , logger )
2021-11-27 09:43:25 +00:00
} ,
}
2022-03-10 14:01:37 +00:00
func Erigon2 ( genesis * core . Genesis , chainConfig * params . ChainConfig , logger log . Logger ) error {
2021-11-27 09:43:25 +00:00
sigs := make ( chan os . Signal , 1 )
interruptCh := make ( chan bool , 1 )
signal . Notify ( sigs , syscall . SIGINT , syscall . SIGTERM )
go func ( ) {
<- sigs
interruptCh <- true
} ( )
2022-03-10 14:01:37 +00:00
2022-01-24 23:12:25 +00:00
historyDb , err := kv2 . NewMDBX ( logger ) . Path ( path . Join ( datadir , "chaindata" ) ) . Open ( )
2021-11-27 09:43:25 +00:00
if err != nil {
2022-01-14 16:02:44 +00:00
return fmt . Errorf ( "opening chaindata as read only: %v" , err )
2021-11-27 09:43:25 +00:00
}
defer historyDb . Close ( )
2022-03-17 07:30:47 +00:00
2021-11-27 09:43:25 +00:00
ctx := context . Background ( )
historyTx , err1 := historyDb . BeginRo ( ctx )
if err1 != nil {
return err1
}
defer historyTx . Rollback ( )
2022-03-23 16:00:06 +00:00
stateDbPath := path . Join ( datadir , "statedb" )
if block == 0 {
if _ , err = os . Stat ( stateDbPath ) ; err != nil {
if ! errors . Is ( err , os . ErrNotExist ) {
return err
}
} else if err = os . RemoveAll ( stateDbPath ) ; err != nil {
return err
}
}
db , err2 := kv2 . NewMDBX ( logger ) . Path ( stateDbPath ) . WriteMap ( ) . Open ( )
if err2 != nil {
return err2
}
defer db . Close ( )
2022-03-17 07:30:47 +00:00
2022-02-12 13:33:09 +00:00
aggPath := filepath . Join ( datadir , "aggregator" )
2022-01-16 08:40:16 +00:00
if block == 0 {
if _ , err = os . Stat ( aggPath ) ; err != nil {
if ! errors . Is ( err , os . ErrNotExist ) {
return err
}
} else if err = os . RemoveAll ( aggPath ) ; err != nil {
return err
}
if err = os . Mkdir ( aggPath , os . ModePerm ) ; err != nil {
2021-11-27 09:43:25 +00:00
return err
}
}
2022-03-17 07:30:47 +00:00
2022-03-23 16:00:06 +00:00
var rwTx kv . RwTx
defer func ( ) {
if rwTx != nil {
rwTx . Rollback ( )
}
} ( )
if rwTx , err = db . BeginRw ( ctx ) ; err != nil {
return err
}
2022-05-05 12:54:29 +00:00
var blockRootMismatchExpected bool
var trieVariant commitment . TrieVariant
switch commitmentTrie {
case "bin" :
trieVariant = commitment . VariantBinPatriciaTrie
blockRootMismatchExpected = true
case "hex" :
fallthrough
default :
trieVariant = commitment . VariantHexPatriciaTrie
}
2022-07-11 14:58:08 +00:00
trie := commitment . InitializeTrie ( trieVariant )
logger . Info ( "commitment trie initialized" , "variant" , trie . Variant ( ) )
agg , err3 := aggregator . NewAggregator ( aggPath , unwindLimit , aggregationStep , changesets , commitments , 100_000_000 , trie , rwTx )
2021-11-27 09:43:25 +00:00
if err3 != nil {
return fmt . Errorf ( "create aggregator: %w" , err3 )
}
2022-01-31 23:40:51 +00:00
defer agg . Close ( )
2022-03-10 14:01:37 +00:00
2021-11-27 09:43:25 +00:00
interrupt := false
2022-03-23 16:00:06 +00:00
w := agg . MakeStateWriter ( changesets /* beforeOn */ )
2022-01-14 16:02:44 +00:00
var rootHash [ ] byte
2022-01-16 08:40:16 +00:00
if block == 0 {
genBlock , genesisIbs , err4 := genesis . ToBlock ( )
if err4 != nil {
return err4
}
2022-03-23 16:00:06 +00:00
if err = w . Reset ( 0 , rwTx ) ; err != nil {
2022-01-16 08:40:16 +00:00
return err
}
2022-05-26 16:20:34 +00:00
if err = genesisIbs . CommitBlock ( & params . Rules { } , & WriterWrapper { w : w } ) ; err != nil {
2022-01-16 08:40:16 +00:00
return fmt . Errorf ( "cannot write state: %w" , err )
}
if err = w . FinishTx ( 0 , false ) ; err != nil {
return err
}
2022-02-12 00:06:57 +00:00
if commitments {
if rootHash , err = w . ComputeCommitment ( false ) ; err != nil {
return err
}
2022-01-16 21:24:54 +00:00
}
if err = w . Aggregate ( false ) ; err != nil {
2022-01-16 08:40:16 +00:00
return err
}
2022-05-05 12:54:29 +00:00
if commitments && ! blockRootMismatchExpected {
2022-02-12 00:06:57 +00:00
if ! bytes . Equal ( rootHash , genBlock . Header ( ) . Root [ : ] ) {
return fmt . Errorf ( "root hash mismatch for genesis block, expected [%x], was [%x]" , genBlock . Header ( ) . Root [ : ] , rootHash )
}
2022-01-16 08:40:16 +00:00
}
2022-01-24 23:12:25 +00:00
}
2022-03-10 14:01:37 +00:00
logger . Info ( "Initialised chain configuration" , "config" , chainConfig )
var (
2022-03-17 07:30:47 +00:00
blockNum uint64
2022-03-10 14:01:37 +00:00
trace bool
2022-03-17 07:30:47 +00:00
vmConfig vm . Config
txNum uint64 = 2 // Consider that each block contains at least first system tx and enclosing transactions, except for Clique consensus engine
2022-03-10 14:01:37 +00:00
)
2022-01-31 23:40:51 +00:00
logEvery := time . NewTicker ( logInterval )
defer logEvery . Stop ( )
2022-03-10 14:01:37 +00:00
statx := & stat {
prevBlock : blockNum ,
prevTime : time . Now ( ) ,
}
2022-03-17 07:30:47 +00:00
go func ( ) {
for range logEvery . C {
2022-01-31 23:40:51 +00:00
aStats := agg . Stats ( )
2022-03-10 14:01:37 +00:00
statx . delta ( aStats , blockNum ) . print ( aStats , logger )
2022-01-31 23:40:51 +00:00
}
2022-03-17 07:30:47 +00:00
} ( )
2022-05-26 03:31:06 +00:00
var blockReader services . FullBlockReader
2022-04-29 06:10:31 +00:00
var allSnapshots * snapshotsync . RoSnapshots
2022-06-05 06:33:55 +00:00
useSnapshots := ethconfig . UseSnapshotsByChainName ( chainConfig . ChainName ) && snapshotsCli
if useSnapshots {
2022-05-30 02:59:38 +00:00
allSnapshots = snapshotsync . NewRoSnapshots ( ethconfig . NewSnapCfg ( true , false , true ) , path . Join ( datadir , "snapshots" ) )
2022-03-17 07:30:47 +00:00
defer allSnapshots . Close ( )
2022-07-28 09:57:38 +00:00
if err := allSnapshots . ReopenWithDB ( db ) ; err != nil {
2022-05-05 12:54:29 +00:00
return fmt . Errorf ( "reopen snapshot segments: %w" , err )
}
2022-03-17 07:30:47 +00:00
blockReader = snapshotsync . NewBlockReaderWithSnapshots ( allSnapshots )
} else {
blockReader = snapshotsync . NewBlockReader ( )
}
2022-04-29 06:10:31 +00:00
engine := initConsensusEngine ( chainConfig , logger , allSnapshots )
2022-03-17 07:30:47 +00:00
for ! interrupt {
2022-01-16 08:40:16 +00:00
blockNum ++
2022-03-17 07:30:47 +00:00
trace = traceBlock > 0 && blockNum == uint64 ( traceBlock )
2022-02-22 01:42:12 +00:00
blockHash , err := blockReader . CanonicalHash ( ctx , historyTx , blockNum )
2021-11-27 09:43:25 +00:00
if err != nil {
return err
}
2022-03-17 07:30:47 +00:00
2022-03-18 09:55:38 +00:00
if blockNum <= block {
2022-02-19 08:15:35 +00:00
_ , _ , txAmount := rawdb . ReadBody ( historyTx , blockHash , blockNum )
2022-03-17 07:30:47 +00:00
2022-02-19 08:15:35 +00:00
// Skip that block, but increase txNum
2022-03-17 07:30:47 +00:00
txNum += uint64 ( txAmount ) + 2 // Pre and Post block transaction
2022-02-19 08:15:35 +00:00
continue
}
2022-03-17 07:30:47 +00:00
block , _ , err := blockReader . BlockWithSenders ( ctx , historyTx , blockHash , blockNum )
2021-11-27 09:43:25 +00:00
if err != nil {
return err
}
2022-03-17 07:30:47 +00:00
if block == nil {
2022-03-10 14:01:37 +00:00
log . Info ( "history: block is nil" , "block" , blockNum )
2021-11-27 09:43:25 +00:00
break
}
2022-03-23 16:00:06 +00:00
if err = w . Reset ( blockNum , rwTx ) ; err != nil {
2021-11-27 09:43:25 +00:00
return err
}
2022-03-17 07:30:47 +00:00
2022-03-23 16:00:06 +00:00
r := agg . MakeStateReader ( blockNum , rwTx )
2022-01-16 21:24:54 +00:00
readWrapper := & ReaderWrapper { r : r , blockNum : blockNum }
writeWrapper := & WriterWrapper { w : w , blockNum : blockNum }
2022-02-22 01:42:12 +00:00
getHeader := func ( hash common . Hash , number uint64 ) * types . Header {
h , err := blockReader . Header ( ctx , historyTx , hash , number )
if err != nil {
panic ( err )
}
return h
}
2022-03-17 07:30:47 +00:00
2022-03-13 23:11:49 +00:00
txNum ++ // Pre-block transaction
2022-03-17 07:30:47 +00:00
if txNum , _ , err = processBlock ( trace , txNum , readWrapper , writeWrapper , chainConfig , engine , getHeader , block , vmConfig ) ; err != nil {
return fmt . Errorf ( "processing block %d: %w" , blockNum , err )
2021-11-27 09:43:25 +00:00
}
2022-01-14 16:02:44 +00:00
if err := w . FinishTx ( txNum , trace ) ; err != nil {
2022-03-17 07:30:47 +00:00
return fmt . Errorf ( "failed to finish tx: %w" , err )
2021-11-27 09:43:25 +00:00
}
2022-01-14 16:02:44 +00:00
if trace {
2022-01-16 08:40:16 +00:00
fmt . Printf ( "FinishTx called for %d block %d\n" , txNum , blockNum )
2022-01-14 16:02:44 +00:00
}
2022-03-17 07:30:47 +00:00
2022-03-13 23:11:49 +00:00
txNum ++ // Post-block transaction
2022-03-17 07:30:47 +00:00
2022-01-24 23:12:25 +00:00
// Check for interrupts
select {
case interrupt = <- interruptCh :
log . Info ( fmt . Sprintf ( "interrupted, please wait for cleanup, next time start with --block %d" , blockNum ) )
default :
}
2022-03-17 07:30:47 +00:00
2022-02-12 00:06:57 +00:00
if commitments && ( interrupt || blockNum % uint64 ( commitmentFrequency ) == 0 ) {
2022-01-16 21:24:54 +00:00
if rootHash , err = w . ComputeCommitment ( trace /* trace */ ) ; err != nil {
2022-01-14 16:02:44 +00:00
return err
}
2022-05-05 12:54:29 +00:00
if ! blockRootMismatchExpected {
if ! bytes . Equal ( rootHash , block . Header ( ) . Root [ : ] ) {
return fmt . Errorf ( "root hash mismatch for block %d, expected [%x], was [%x]" , blockNum , block . Header ( ) . Root [ : ] , rootHash )
}
2022-01-14 16:02:44 +00:00
}
2022-01-16 21:24:54 +00:00
}
if err = w . Aggregate ( trace ) ; err != nil {
return err
}
2022-03-23 16:00:06 +00:00
// Commit transaction only when interrupted or just before computing commitment (so it can be re-done)
commit := interrupt
if ! commit && ( blockNum + 1 ) % uint64 ( commitmentFrequency ) == 0 {
var spaceDirty uint64
if spaceDirty , _ , err = rwTx . ( * mdbx . MdbxTx ) . SpaceDirty ( ) ; err != nil {
return fmt . Errorf ( "retrieving spaceDirty: %w" , err )
}
if spaceDirty >= dirtySpaceThreshold {
log . Info ( "Initiated tx commit" , "block" , blockNum , "space dirty" , libcommon . ByteCount ( spaceDirty ) )
commit = true
}
}
if commit {
if err = rwTx . Commit ( ) ; err != nil {
return err
}
if ! interrupt {
if rwTx , err = db . BeginRw ( ctx ) ; err != nil {
return err
}
}
}
2021-11-27 09:43:25 +00:00
}
2022-03-10 14:01:37 +00:00
aStats := agg . Stats ( )
statx . delta ( aStats , blockNum ) . print ( aStats , logger )
2022-01-16 08:40:16 +00:00
if w != nil {
w . Close ( )
}
2021-11-27 09:43:25 +00:00
return nil
}
2022-03-10 14:01:37 +00:00
type stat struct {
blockNum uint64
hits uint64
misses uint64
prevBlock uint64
prevMisses uint64
prevHits uint64
hitMissRatio float64
speed float64
prevTime time . Time
mem runtime . MemStats
}
func ( s * stat ) print ( aStats aggregator . FilesStats , logger log . Logger ) {
totalFiles := aStats . AccountsCount + aStats . CodeCount + aStats . StorageCount + aStats . CommitmentCount
totalDatSize := aStats . AccountsDatSize + aStats . CodeDatSize + aStats . StorageDatSize + aStats . CommitmentDatSize
totalIdxSize := aStats . AccountsIdxSize + aStats . CodeIdxSize + aStats . StorageIdxSize + aStats . CommitmentIdxSize
logger . Info ( "Progress" , "block" , s . blockNum , "blk/s" , s . speed , "state files" , totalFiles ,
"accounts" , libcommon . ByteCount ( uint64 ( aStats . AccountsDatSize + aStats . AccountsIdxSize ) ) ,
"code" , libcommon . ByteCount ( uint64 ( aStats . CodeDatSize + aStats . CodeIdxSize ) ) ,
"storage" , libcommon . ByteCount ( uint64 ( aStats . StorageDatSize + aStats . StorageIdxSize ) ) ,
"commitment" , libcommon . ByteCount ( uint64 ( aStats . CommitmentDatSize + aStats . CommitmentIdxSize ) ) ,
"total dat" , libcommon . ByteCount ( uint64 ( totalDatSize ) ) , "total idx" , libcommon . ByteCount ( uint64 ( totalIdxSize ) ) ,
"hit ratio" , s . hitMissRatio , "hits+misses" , s . hits + s . misses ,
"alloc" , libcommon . ByteCount ( s . mem . Alloc ) , "sys" , libcommon . ByteCount ( s . mem . Sys ) ,
)
}
func ( s * stat ) delta ( aStats aggregator . FilesStats , blockNum uint64 ) * stat {
currentTime := time . Now ( )
2022-05-19 04:48:07 +00:00
libcommon . ReadMemStats ( & s . mem )
2022-03-10 14:01:37 +00:00
interval := currentTime . Sub ( s . prevTime ) . Seconds ( )
s . blockNum = blockNum
s . speed = float64 ( s . blockNum - s . prevBlock ) / interval
s . prevBlock = blockNum
s . prevTime = currentTime
s . hits = aStats . Hits - s . prevHits
s . misses = aStats . Misses - s . prevMisses
s . prevHits = aStats . Hits
s . prevMisses = aStats . Misses
total := s . hits + s . misses
if total > 0 {
s . hitMissRatio = float64 ( s . hits ) / float64 ( total )
}
return s
}
2022-03-17 07:30:47 +00:00
func processBlock ( trace bool , txNumStart uint64 , rw * ReaderWrapper , ww * WriterWrapper , chainConfig * params . ChainConfig , engine consensus . Engine , getHeader func ( hash common . Hash , number uint64 ) * types . Header , block * types . Block , vmConfig vm . Config ) ( uint64 , types . Receipts , error ) {
2022-02-22 01:55:49 +00:00
defer blockExecutionTimer . UpdateDuration ( time . Now ( ) )
2022-03-17 07:30:47 +00:00
2022-01-14 16:02:44 +00:00
header := block . Header ( )
vmConfig . TraceJumpDest = true
gp := new ( core . GasPool ) . AddGas ( block . GasLimit ( ) )
usedGas := new ( uint64 )
var receipts types . Receipts
2022-01-24 23:12:25 +00:00
daoBlock := chainConfig . DAOForkSupport && chainConfig . DAOForkBlock != nil && chainConfig . DAOForkBlock . Cmp ( block . Number ( ) ) == 0
2022-01-14 16:02:44 +00:00
rules := chainConfig . Rules ( block . NumberU64 ( ) )
txNum := txNumStart
2022-03-17 07:30:47 +00:00
2022-01-14 16:02:44 +00:00
for i , tx := range block . Transactions ( ) {
2022-01-24 23:12:25 +00:00
ibs := state . New ( rw )
if daoBlock {
misc . ApplyDAOHardFork ( ibs )
daoBlock = false
}
2022-01-14 16:02:44 +00:00
ibs . Prepare ( tx . Hash ( ) , block . Hash ( ) , i )
2022-07-07 11:47:00 +00:00
receipt , _ , err := core . ApplyTransaction ( chainConfig , core . GetHashFn ( header , getHeader ) , engine , nil , gp , ibs , ww , header , tx , usedGas , vmConfig , nil )
2022-01-14 16:02:44 +00:00
if err != nil {
return 0 , nil , fmt . Errorf ( "could not apply tx %d [%x] failed: %w" , i , tx . Hash ( ) , err )
}
receipts = append ( receipts , receipt )
if err = ww . w . FinishTx ( txNum , trace ) ; err != nil {
return 0 , nil , fmt . Errorf ( "finish tx %d [%x] failed: %w" , i , tx . Hash ( ) , err )
}
if trace {
fmt . Printf ( "FinishTx called for %d [%x]\n" , txNum , tx . Hash ( ) )
}
txNum ++
}
2022-01-24 23:12:25 +00:00
ibs := state . New ( rw )
2022-03-17 07:30:47 +00:00
2022-01-14 16:02:44 +00:00
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
2022-01-15 09:41:56 +00:00
if _ , _ , _ , err := engine . FinalizeAndAssemble ( chainConfig , header , ibs , block . Transactions ( ) , block . Uncles ( ) , receipts , nil , nil , nil , nil ) ; err != nil {
2022-01-14 16:02:44 +00:00
return 0 , nil , fmt . Errorf ( "finalize of block %d failed: %w" , block . NumberU64 ( ) , err )
}
if err := ibs . CommitBlock ( rules , ww ) ; err != nil {
return 0 , nil , fmt . Errorf ( "committing block %d failed: %w" , block . NumberU64 ( ) , err )
}
return txNum , receipts , nil
}
2021-11-27 09:43:25 +00:00
// Implements StateReader and StateWriter
type ReaderWrapper struct {
blockNum uint64
r * aggregator . Reader
}
type WriterWrapper struct {
blockNum uint64
w * aggregator . Writer
}
2022-01-14 16:02:44 +00:00
func bytesToUint64 ( buf [ ] byte ) ( x uint64 ) {
for i , b := range buf {
x = x << 8 + uint64 ( b )
if i == 7 {
return
}
}
return
}
2021-11-27 09:43:25 +00:00
func ( rw * ReaderWrapper ) ReadAccountData ( address common . Address ) ( * accounts . Account , error ) {
2022-03-23 16:00:06 +00:00
enc , err := rw . r . ReadAccountData ( address . Bytes ( ) , false /* trace */ )
if err != nil {
return nil , err
}
2021-11-27 09:43:25 +00:00
if len ( enc ) == 0 {
return nil , nil
}
2022-01-14 16:02:44 +00:00
2021-11-27 09:43:25 +00:00
var a accounts . Account
2022-01-14 16:02:44 +00:00
a . Reset ( )
pos := 0
nonceBytes := int ( enc [ pos ] )
pos ++
if nonceBytes > 0 {
a . Nonce = bytesToUint64 ( enc [ pos : pos + nonceBytes ] )
pos += nonceBytes
}
balanceBytes := int ( enc [ pos ] )
pos ++
if balanceBytes > 0 {
a . Balance . SetBytes ( enc [ pos : pos + balanceBytes ] )
pos += balanceBytes
}
codeHashBytes := int ( enc [ pos ] )
pos ++
if codeHashBytes > 0 {
copy ( a . CodeHash [ : ] , enc [ pos : pos + codeHashBytes ] )
pos += codeHashBytes
}
incBytes := int ( enc [ pos ] )
pos ++
if incBytes > 0 {
a . Incarnation = bytesToUint64 ( enc [ pos : pos + incBytes ] )
2021-11-27 09:43:25 +00:00
}
return & a , nil
}
func ( rw * ReaderWrapper ) ReadAccountStorage ( address common . Address , incarnation uint64 , key * common . Hash ) ( [ ] byte , error ) {
trace := false
2022-03-23 16:00:06 +00:00
enc , err := rw . r . ReadAccountStorage ( address . Bytes ( ) , key . Bytes ( ) , trace )
if err != nil {
return nil , err
}
2021-11-27 09:43:25 +00:00
if enc == nil {
return nil , nil
}
2022-03-23 16:00:06 +00:00
return enc , nil
2021-11-27 09:43:25 +00:00
}
func ( rw * ReaderWrapper ) ReadAccountCode ( address common . Address , incarnation uint64 , codeHash common . Hash ) ( [ ] byte , error ) {
2022-03-23 16:00:06 +00:00
return rw . r . ReadAccountCode ( address . Bytes ( ) , false /* trace */ )
2021-11-27 09:43:25 +00:00
}
func ( rw * ReaderWrapper ) ReadAccountCodeSize ( address common . Address , incarnation uint64 , codeHash common . Hash ) ( int , error ) {
2022-03-23 16:00:06 +00:00
return rw . r . ReadAccountCodeSize ( address . Bytes ( ) , false /* trace */ )
2021-11-27 09:43:25 +00:00
}
func ( rw * ReaderWrapper ) ReadAccountIncarnation ( address common . Address ) ( uint64 , error ) {
return 0 , nil
}
func ( ww * WriterWrapper ) UpdateAccountData ( address common . Address , original , account * accounts . Account ) error {
2022-01-14 16:02:44 +00:00
var l int
l ++
if account . Nonce > 0 {
l += ( bits . Len64 ( account . Nonce ) + 7 ) / 8
}
l ++
if ! account . Balance . IsZero ( ) {
l += account . Balance . ByteLen ( )
}
l ++
if ! account . IsEmptyCodeHash ( ) {
l += 32
}
l ++
if account . Incarnation > 0 {
l += ( bits . Len64 ( account . Incarnation ) + 7 ) / 8
}
value := make ( [ ] byte , l )
pos := 0
if account . Nonce == 0 {
value [ pos ] = 0
pos ++
} else {
nonceBytes := ( bits . Len64 ( account . Nonce ) + 7 ) / 8
value [ pos ] = byte ( nonceBytes )
var nonce = account . Nonce
for i := nonceBytes ; i > 0 ; i -- {
value [ pos + i ] = byte ( nonce )
nonce >>= 8
}
pos += nonceBytes + 1
}
if account . Balance . IsZero ( ) {
value [ pos ] = 0
pos ++
} else {
balanceBytes := account . Balance . ByteLen ( )
value [ pos ] = byte ( balanceBytes )
pos ++
account . Balance . WriteToSlice ( value [ pos : pos + balanceBytes ] )
pos += balanceBytes
}
if account . IsEmptyCodeHash ( ) {
value [ pos ] = 0
pos ++
} else {
value [ pos ] = 32
pos ++
copy ( value [ pos : pos + 32 ] , account . CodeHash [ : ] )
pos += 32
}
if account . Incarnation == 0 {
value [ pos ] = 0
} else {
incBytes := ( bits . Len64 ( account . Incarnation ) + 7 ) / 8
value [ pos ] = byte ( incBytes )
var inc = account . Incarnation
for i := incBytes ; i > 0 ; i -- {
value [ pos + i ] = byte ( inc )
inc >>= 8
}
}
2022-03-23 16:00:06 +00:00
if err := ww . w . UpdateAccountData ( address . Bytes ( ) , value , false /* trace */ ) ; err != nil {
return err
}
2021-11-27 09:43:25 +00:00
return nil
}
func ( ww * WriterWrapper ) UpdateAccountCode ( address common . Address , incarnation uint64 , codeHash common . Hash , code [ ] byte ) error {
2022-03-23 16:00:06 +00:00
if err := ww . w . UpdateAccountCode ( address . Bytes ( ) , code , false /* trace */ ) ; err != nil {
return err
}
2021-11-27 09:43:25 +00:00
return nil
}
func ( ww * WriterWrapper ) DeleteAccount ( address common . Address , original * accounts . Account ) error {
2022-03-23 16:00:06 +00:00
if err := ww . w . DeleteAccount ( address . Bytes ( ) , false /* trace */ ) ; err != nil {
return err
}
2021-11-27 09:43:25 +00:00
return nil
}
func ( ww * WriterWrapper ) WriteAccountStorage ( address common . Address , incarnation uint64 , key * common . Hash , original , value * uint256 . Int ) error {
trace := false
if trace {
fmt . Printf ( "block %d, WriteAccountStorage %x %x, original %s, value %s\n" , ww . blockNum , address , * key , original , value )
}
2022-03-23 16:00:06 +00:00
if err := ww . w . WriteAccountStorage ( address . Bytes ( ) , key . Bytes ( ) , value . Bytes ( ) , trace ) ; err != nil {
return err
}
2021-11-27 09:43:25 +00:00
return nil
}
func ( ww * WriterWrapper ) CreateContract ( address common . Address ) error {
return nil
}
2022-03-17 07:30:47 +00:00
2022-04-29 06:10:31 +00:00
func initConsensusEngine ( chainConfig * params . ChainConfig , logger log . Logger , snapshots * snapshotsync . RoSnapshots ) ( engine consensus . Engine ) {
2022-03-17 07:30:47 +00:00
config := ethconfig . Defaults
switch {
case chainConfig . Clique != nil :
c := params . CliqueSnapshot
c . DBPath = filepath . Join ( datadir , "clique" , "db" )
2022-07-31 20:54:23 +00:00
engine = ethconsensusconfig . CreateConsensusEngine ( chainConfig , logger , c , config . Miner . Notify , config . Miner . Noverify , "" , true , datadir , snapshots , true /* readonly */ )
2022-03-17 07:30:47 +00:00
case chainConfig . Aura != nil :
consensusConfig := & params . AuRaConfig { DBPath : filepath . Join ( datadir , "aura" ) }
2022-07-31 20:54:23 +00:00
engine = ethconsensusconfig . CreateConsensusEngine ( chainConfig , logger , consensusConfig , config . Miner . Notify , config . Miner . Noverify , "" , true , datadir , snapshots , true /* readonly */ )
2022-03-17 07:30:47 +00:00
case chainConfig . Parlia != nil :
consensusConfig := & params . ParliaConfig { DBPath : filepath . Join ( datadir , "parlia" ) }
2022-07-31 20:54:23 +00:00
engine = ethconsensusconfig . CreateConsensusEngine ( chainConfig , logger , consensusConfig , config . Miner . Notify , config . Miner . Noverify , "" , true , datadir , snapshots , true /* readonly */ )
2022-03-17 07:30:47 +00:00
case chainConfig . Bor != nil :
consensusConfig := & config . Bor
2022-07-31 20:54:23 +00:00
engine = ethconsensusconfig . CreateConsensusEngine ( chainConfig , logger , consensusConfig , config . Miner . Notify , config . Miner . Noverify , "http://localhost:1317" , false , datadir , snapshots , true /* readonly */ )
2022-03-17 07:30:47 +00:00
default : //ethash
engine = ethash . NewFaker ( )
}
return
}