[erigon2] optional writing of "before" value for changes, decouple commitment from blocks (#3272)

* Sepatate commitment calculation from blocks

* Fix

* Fix lint

Co-authored-by: Alex Sharp <alexsharp@Alexs-MacBook-Pro.local>
This commit is contained in:
ledgerwatch 2022-01-16 21:24:54 +00:00 committed by GitHub
parent 17aff6090f
commit 1af72faf71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 86 deletions

View File

@ -30,15 +30,15 @@ import (
)
var (
check bool
changesets bool
commitmentFrequency int // How many blocks to skip between calculating commitment
changesets bool
)
func init() {
withBlock(erigon2Cmd)
withDatadir(erigon2Cmd)
erigon2Cmd.Flags().BoolVar(&check, "check", false, "set to true to compare state reads with with historical state (for debugging)")
erigon2Cmd.Flags().BoolVar(&changesets, "changesets", false, "set to true to generate changesets")
erigon2Cmd.Flags().IntVar(&commitmentFrequency, "commfreq", 256, "how many blocks to skip between calculating commitment")
rootCmd.AddCommand(erigon2Cmd)
}
@ -46,6 +46,9 @@ 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 {
if commitmentFrequency < 1 || commitmentFrequency > 4096 {
return fmt.Errorf("commitmentFrequency cannot be less than 1 or more than 4096: %d", commitmentFrequency)
}
logger := log.New()
return Erigon2(genesis, logger)
},
@ -109,7 +112,7 @@ func Erigon2(genesis *core.Genesis, logger log.Logger) error {
interrupt := false
blockNum := block
w := agg.MakeStateWriter()
w := agg.MakeStateWriter(false /* beforeOn */)
var rwTx kv.RwTx
defer func() {
if rwTx != nil {
@ -134,7 +137,10 @@ func Erigon2(genesis *core.Genesis, logger log.Logger) error {
if err = w.FinishTx(0, false); err != nil {
return err
}
if rootHash, err = w.FinishBlock(false); err != nil {
if rootHash, err = w.ComputeCommitment(false); err != nil {
return err
}
if err = w.Aggregate(false); err != nil {
return err
}
if !bytes.Equal(rootHash, genBlock.Header().Root[:]) {
@ -173,16 +179,14 @@ func Erigon2(genesis *core.Genesis, logger log.Logger) error {
return err
}
r := agg.MakeStateReader(tx, blockNum)
var checkR state.StateReader
if check {
checkR = state.NewPlainState(historyTx, blockNum-1)
}
if err = w.Reset(rwTx, blockNum); err != nil {
return err
}
intraBlockState := state.New(&ReaderWrapper{r: r, checkR: checkR, blockNum: blockNum})
readWrapper := &ReaderWrapper{r: r, blockNum: blockNum}
writeWrapper := &WriterWrapper{w: w, blockNum: blockNum}
intraBlockState := state.New(readWrapper)
getHeader := func(hash common.Hash, number uint64) *types.Header { return rawdb.ReadHeader(historyTx, hash, number) }
if txNum, _, err = runBlock2(trace, txNum, intraBlockState, &WriterWrapper{w: w, blockNum: blockNum}, chainConfig, getHeader, nil, b, vmConfig); err != nil {
if txNum, _, err = runBlock2(trace, txNum, intraBlockState, readWrapper, writeWrapper, chainConfig, getHeader, nil, b, vmConfig); err != nil {
return fmt.Errorf("block %d: %w", blockNum, err)
}
if blockNum%1000 == 0 {
@ -202,21 +206,26 @@ func Erigon2(genesis *core.Genesis, logger log.Logger) error {
fmt.Printf("FinishTx called for %d block %d\n", txNum, blockNum)
}
txNum++
if rootHash, err = w.FinishBlock(trace /* trace */); err != nil {
return err
}
if bytes.Equal(rootHash, b.Header().Root[:]) {
if err = rwTx.Commit(); err != nil {
if interrupt || blockNum%uint64(commitmentFrequency) == 0 {
if rootHash, err = w.ComputeCommitment(trace /* trace */); err != nil {
return err
}
} else {
if trace {
return fmt.Errorf("root hash mismatch for block %d, expected [%x], was [%x]", blockNum, b.Header().Root[:], rootHash)
} else {
blockNum--
trace = true
if !bytes.Equal(rootHash, b.Header().Root[:]) {
if trace || interrupt {
return fmt.Errorf("root hash mismatch for block %d, expected [%x], was [%x]", blockNum, b.Header().Root[:], rootHash)
} else {
blockNum--
trace = true
}
rwTx.Rollback()
continue
}
rwTx.Rollback()
}
if err = w.Aggregate(trace); err != nil {
return err
}
if err = rwTx.Commit(); err != nil {
return err
}
}
if w != nil {
@ -225,7 +234,7 @@ func Erigon2(genesis *core.Genesis, logger log.Logger) error {
return nil
}
func runBlock2(trace bool, txNumStart uint64, ibs *state.IntraBlockState, ww *WriterWrapper,
func runBlock2(trace bool, txNumStart uint64, ibs *state.IntraBlockState, rw *ReaderWrapper, ww *WriterWrapper,
chainConfig *params.ChainConfig, getHeader func(hash common.Hash, number uint64) *types.Header, contractHasTEVM func(common.Hash) (bool, error), block *types.Block, vmConfig vm.Config) (uint64, types.Receipts, error) {
header := block.Header()
vmConfig.TraceJumpDest = true
@ -270,7 +279,6 @@ func runBlock2(trace bool, txNumStart uint64, ibs *state.IntraBlockState, ww *Wr
type ReaderWrapper struct {
blockNum uint64
r *aggregator.Reader
checkR state.StateReader
}
type WriterWrapper struct {
@ -293,19 +301,7 @@ func (rw *ReaderWrapper) ReadAccountData(address common.Address) (*accounts.Acco
if err != nil {
return nil, err
}
var checkA *accounts.Account
var checkErr error
if rw.checkR != nil {
if checkA, checkErr = rw.checkR.ReadAccountData(address); checkErr != nil {
fmt.Printf("readAccountData %x checkR: %v\n", address, checkErr)
return nil, fmt.Errorf("readAccountData %x checkR: %w", address, checkErr)
}
}
if len(enc) == 0 {
if checkA != nil {
fmt.Printf("readAccountData %x enc [%x], checkEnc [%+v]\n", address, enc, checkA)
return nil, fmt.Errorf("readAccountData %x enc [%x], checkEnc [%+v]", address, enc, checkA)
}
return nil, nil
}
@ -335,12 +331,6 @@ func (rw *ReaderWrapper) ReadAccountData(address common.Address) (*accounts.Acco
if incBytes > 0 {
a.Incarnation = bytesToUint64(enc[pos : pos+incBytes])
}
if rw.checkR != nil {
if !a.Equals(checkA) {
fmt.Printf("readAccountData %x enc [%+v], checkEnc [%+v]\n", address, a, checkA)
return nil, fmt.Errorf("readAccountData %x enc [%+v], checkEnc [%+v]", address, a, checkA)
}
}
return &a, nil
}
@ -350,27 +340,9 @@ func (rw *ReaderWrapper) ReadAccountStorage(address common.Address, incarnation
if err != nil {
return nil, err
}
var checkEnc []byte
var checkErr error
if rw.checkR != nil {
if checkEnc, checkErr = rw.checkR.ReadAccountStorage(address, incarnation, key); checkErr != nil {
fmt.Printf("block %d ReadAccountStorage %x %x checkR: %v\n", rw.blockNum, address, *key, checkErr)
return nil, fmt.Errorf("readAccountStorage %x %x checkR: %w", address, *key, checkErr)
}
}
if enc == nil {
if len(checkEnc) != 0 {
fmt.Printf("block %d ReadAccountStorage %x %x enc [%x], checkEnc [%x]\n", rw.blockNum, address, *key, enc, checkEnc)
return nil, fmt.Errorf("readAccountStorage %x %x enc [%x], checkEnc [%x]", address, *key, enc, checkEnc)
}
return nil, nil
}
if rw.checkR != nil {
if !bytes.Equal(enc.Bytes(), checkEnc) {
fmt.Printf("block %d ReadAccountStorage %x %x enc [%x], checkEnc [%x]\n", rw.blockNum, address, *key, enc, checkEnc)
return nil, fmt.Errorf("readAccountStorage %x %x enc [%x], checkEnc [%x]", address, *key, enc, checkEnc)
}
}
return enc.Bytes(), nil
}
@ -379,17 +351,6 @@ func (rw *ReaderWrapper) ReadAccountCode(address common.Address, incarnation uin
if err != nil {
return nil, err
}
if rw.checkR != nil {
checkEnc, checkErr := rw.checkR.ReadAccountCode(address, incarnation, codeHash)
if checkErr != nil {
fmt.Printf("readAccountCode %x checkR: %v\n", address, checkErr)
return nil, fmt.Errorf("readAccountCode %x checkR: %w", address, checkErr)
}
if !bytes.Equal(enc, checkEnc) {
fmt.Printf("readAccountCode %x enc [%x], checkEnc [%x]\n", address, enc, checkEnc)
return nil, fmt.Errorf("readAccountCode %x enc [%x], checkEnc [%x]", address, enc, checkEnc)
}
}
return enc, nil
}
@ -398,17 +359,6 @@ func (rw *ReaderWrapper) ReadAccountCodeSize(address common.Address, incarnation
if err != nil {
return 0, err
}
/*
checkEnc, checkErr := rw.checkR.ReadAccountCode(address, incarnation, codeHash)
if checkErr != nil {
fmt.Printf("readAccountCode %x checkR: %v\n", address, checkErr)
return 0, fmt.Errorf("readAccountCode %x checkR: %w", address, checkErr)
}
if !bytes.Equal(enc, checkEnc) {
fmt.Printf("readAccountCode %x enc [%x], checkEnc [%x]\n", address, enc, checkEnc)
return 0, fmt.Errorf("readAccountCode %x enc [%x], checkEnc [%x]", address, enc, checkEnc)
}
*/
return len(enc), nil
}

2
go.mod
View File

@ -39,7 +39,7 @@ require (
github.com/json-iterator/go v1.1.12
github.com/julienschmidt/httprouter v1.3.0
github.com/kevinburke/go-bindata v3.21.0+incompatible
github.com/ledgerwatch/erigon-lib v0.0.0-20220115220906-e5c07ec90155
github.com/ledgerwatch/erigon-lib v0.0.0-20220116202744-0eaa0333e1a7
github.com/ledgerwatch/log/v3 v3.4.0
github.com/ledgerwatch/secp256k1 v1.0.0
github.com/logrusorgru/aurora/v3 v3.0.0

4
go.sum
View File

@ -634,8 +634,8 @@ github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3P
github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/ledgerwatch/erigon-lib v0.0.0-20220115220906-e5c07ec90155 h1:rmGlJCn1sBp9cbzTc5kuzYHk7ASZeKCrNi9t5Sw1zM4=
github.com/ledgerwatch/erigon-lib v0.0.0-20220115220906-e5c07ec90155/go.mod h1:RtMyitRZlGyq0k8YVbMIwN/w3iby0zhPfM3tpCoqSUU=
github.com/ledgerwatch/erigon-lib v0.0.0-20220116202744-0eaa0333e1a7 h1:2XIu4aAnq6Gn2ynSrO9AvzhFmtOXWC2/QBd+AZtJL0M=
github.com/ledgerwatch/erigon-lib v0.0.0-20220116202744-0eaa0333e1a7/go.mod h1:RtMyitRZlGyq0k8YVbMIwN/w3iby0zhPfM3tpCoqSUU=
github.com/ledgerwatch/log/v3 v3.4.0 h1:SEIOcv5a2zkG3PmoT5jeTU9m/0nEUv0BJS5bzsjwKCI=
github.com/ledgerwatch/log/v3 v3.4.0/go.mod h1:VXcz6Ssn6XEeU92dCMc39/g1F0OYAjw1Mt+dGP5DjXY=
github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ=