diff --git a/README.md b/README.md index 39654577e..ec5747eba 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,6 @@ System Requirements * Gnosis Chain Archive: 370GB (January 2023). -* BSC Archive: 7TB. BSC Full: 1TB. (April 2022). - * Polygon Mainnet Archive: 5TB. Polygon Mumbai Archive: 1TB. (April 2022). SSD or NVMe. Do not recommend HDD - on HDD Erigon will always stay N blocks behind chain tip, but not fall behind. @@ -97,7 +95,7 @@ make erigon ./build/bin/erigon ``` -Default `--snapshots` for `mainnet`, `goerli`, `gnosis`, `bsc`. Other networks now have default `--snapshots=false`. +Default `--snapshots` for `mainnet`, `goerli`, `gnosis`, `chiado`. Other networks now have default `--snapshots=false`. Increase download speed by flag `--torrent.download.rate=20mb`. 🔬 See [Downloader docs](./cmd/downloader/readme.md) diff --git a/cmd/erigon-el/backend/backend.go b/cmd/erigon-el/backend/backend.go index 4730b2365..b2011e639 100644 --- a/cmd/erigon-el/backend/backend.go +++ b/cmd/erigon-el/backend/backend.go @@ -16,6 +16,12 @@ import ( "github.com/c2h5oh/datasize" "github.com/holiman/uint256" + "github.com/ledgerwatch/log/v3" + "golang.org/x/exp/slices" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/protobuf/types/known/emptypb" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/datadir" @@ -39,18 +45,6 @@ import ( txpool2 "github.com/ledgerwatch/erigon-lib/txpool" "github.com/ledgerwatch/erigon-lib/txpool/txpooluitl" types2 "github.com/ledgerwatch/erigon-lib/types" - "github.com/ledgerwatch/log/v3" - "golang.org/x/exp/slices" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - "google.golang.org/protobuf/types/known/emptypb" - - "github.com/ledgerwatch/erigon/core/systemcontracts" - - "github.com/ledgerwatch/erigon/core/state/historyv2read" - "github.com/ledgerwatch/erigon/core/types/accounts" - "github.com/ledgerwatch/erigon/p2p/dnsdisc" - "github.com/ledgerwatch/erigon/p2p/enode" "github.com/ledgerwatch/erigon/cmd/erigon-el/eth1" stages3 "github.com/ledgerwatch/erigon/cmd/erigon-el/stages" @@ -62,12 +56,14 @@ import ( "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/clique" "github.com/ledgerwatch/erigon/consensus/ethash" - "github.com/ledgerwatch/erigon/consensus/parlia" "github.com/ledgerwatch/erigon/consensus/serenity" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" + "github.com/ledgerwatch/erigon/core/state/historyv2read" "github.com/ledgerwatch/erigon/core/state/temporal" + "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/core/types/accounts" "github.com/ledgerwatch/erigon/core/vm" "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/eth/ethconfig" @@ -80,6 +76,8 @@ import ( "github.com/ledgerwatch/erigon/ethstats" "github.com/ledgerwatch/erigon/node" "github.com/ledgerwatch/erigon/p2p" + "github.com/ledgerwatch/erigon/p2p/dnsdisc" + "github.com/ledgerwatch/erigon/p2p/enode" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/engineapi" @@ -208,11 +206,6 @@ func NewBackend(stack *node.Node, config *ethconfig.Config, logger log.Logger) ( log.Info("Initialised chain configuration", "config", chainConfig, "genesis", genesis.Hash()) - // Apply special hacks for BSC params - if chainConfig.Parlia != nil { - params.ApplyBinanceSmartChainParams() - } - if err := chainKv.Update(context.Background(), func(tx kv.RwTx) error { if err = stagedsync.UpdateMetrics(tx); err != nil { return err @@ -420,8 +413,6 @@ func NewBackend(stack *node.Node, config *ethconfig.Config, logger log.Logger) ( } else if chainConfig.Aura != nil { config.Aura.Etherbase = config.Miner.Etherbase consensusConfig = &config.Aura - } else if chainConfig.Parlia != nil { - consensusConfig = &config.Parlia } else if chainConfig.Bor != nil { consensusConfig = &config.Bor } else { @@ -729,25 +720,6 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy }) } - var prl *parlia.Parlia - if p, ok := s.engine.(*parlia.Parlia); ok { - prl = p - } else if cl, ok := s.engine.(*serenity.Serenity); ok { - if p, ok := cl.InnerEngine().(*parlia.Parlia); ok { - prl = p - } - } - if prl != nil { - if cfg.SigKey == nil { - log.Error("Etherbase account unavailable locally", "err", err) - return fmt.Errorf("signer missing: %w", err) - } - - prl.Authorize(eb, func(validator libcommon.Address, payload []byte, chainId *big.Int) ([]byte, error) { - return crypto.Sign(payload, cfg.SigKey) - }) - } - var borcfg *bor.Bor if b, ok := s.engine.(*bor.Bor); ok { borcfg = b diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index a28ac2f8f..81066193e 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -1292,11 +1292,6 @@ func newDomains(ctx context.Context, db kv.RwDB, stepSize uint64, mode libstate. } //log.Info("Initialised chain configuration", "config", chainConfig) - // Apply special hacks for BSC params - if chainConfig.Parlia != nil { - params.ApplyBinanceSmartChainParams() - } - var batchSize datasize.ByteSize must(batchSize.UnmarshalText([]byte(batchSizeStr))) @@ -1332,11 +1327,6 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig) } //log.Info("Initialised chain configuration", "config", chainConfig) - // Apply special hacks for BSC params - if chainConfig.Parlia != nil { - params.ApplyBinanceSmartChainParams() - } - var batchSize datasize.ByteSize must(batchSize.UnmarshalText([]byte(batchSizeStr))) @@ -1445,8 +1435,6 @@ func initConsensusEngine(cc *chain2.Config, datadir string, db kv.RwDB) (engine } else if cc.Aura != nil { config.Aura.Etherbase = config.Miner.Etherbase consensusConfig = &config.Aura - } else if cc.Parlia != nil { - consensusConfig = &config.Parlia } else if cc.Bor != nil { consensusConfig = &config.Bor } else { diff --git a/cmd/state/commands/erigon4.go b/cmd/state/commands/erigon4.go index 2bb5089b3..849fb866f 100644 --- a/cmd/state/commands/erigon4.go +++ b/cmd/state/commands/erigon4.go @@ -607,8 +607,6 @@ func initConsensusEngine(cc *chain2.Config, snapshots *snapshotsync.RoSnapshots) } else if cc.Aura != nil { config.Aura.Etherbase = config.Miner.Etherbase consensusConfig = &config.Aura - } else if cc.Parlia != nil { - consensusConfig = &config.Parlia } else if cc.Bor != nil { consensusConfig = &config.Bor } else { diff --git a/cmd/state/commands/root.go b/cmd/state/commands/root.go index ddbca2889..729a1d9f3 100644 --- a/cmd/state/commands/root.go +++ b/cmd/state/commands/root.go @@ -46,10 +46,6 @@ var rootCmd = &cobra.Command{ utils.Fatalf("provided genesis.json chain configuration is invalid: expected chainId to be %v, got %v", chainConfig.ChainID.String(), genesis.Config.ChainID.String()) } - // Apply special hacks for BSC params - if chainConfig.Parlia != nil { - params.ApplyBinanceSmartChainParams() - } if chaindata == "" { chaindata = filepath.Join(datadirCli, "chaindata") diff --git a/cmd/state/exec3/state.go b/cmd/state/exec3/state.go index 036e87778..c196eb9ab 100644 --- a/cmd/state/exec3/state.go +++ b/cmd/state/exec3/state.go @@ -5,11 +5,12 @@ import ( "math/big" "sync" + "github.com/ledgerwatch/log/v3" + "golang.org/x/sync/errgroup" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/log/v3" - "golang.org/x/sync/errgroup" "github.com/ledgerwatch/erigon/cmd/state/exec22" "github.com/ledgerwatch/erigon/consensus" @@ -17,7 +18,6 @@ import ( "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/state" - "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/core/vm" "github.com/ledgerwatch/erigon/core/vm/evmtypes" @@ -42,8 +42,6 @@ type Worker struct { genesis *types.Genesis resultCh *exec22.ResultsQueue chain ChainReader - isPoSA bool - posa consensus.PoSA callTracer *CallTracer taskGasPool *core.GasPool @@ -83,7 +81,6 @@ func NewWorker(lock sync.Locker, ctx context.Context, background bool, chainDb k w.ibs = state.New(w.stateReader) - w.posa, w.isPoSA = engine.(consensus.PoSA) return w } @@ -154,9 +151,6 @@ func (rw *Worker) RunTxTaskNoLock(txTask *exec22.TxTask) { } else if txTask.TxIndex == -1 { // Block initialisation //fmt.Printf("txNum=%d, blockNum=%d, initialisation of the block\n", txTask.TxNum, txTask.BlockNum) - if rw.isPoSA { - systemcontracts.UpgradeBuildInSystemContract(rw.chainConfig, header.Number, ibs) - } syscall := func(contract libcommon.Address, data []byte) ([]byte, error) { return core.SysCallContract(contract, data, *rw.chainConfig, ibs, header, rw.engine, false /* constCall */, nil /*excessDataGas*/) } @@ -184,14 +178,6 @@ func (rw *Worker) RunTxTaskNoLock(txTask *exec22.TxTask) { } } else { //fmt.Printf("txNum=%d, blockNum=%d, txIndex=%d\n", txTask.TxNum, txTask.BlockNum, txTask.TxIndex) - if rw.isPoSA { - if isSystemTx, err := rw.posa.IsSystemTransaction(txTask.Tx, header); err != nil { - panic(err) - } else if isSystemTx { - //fmt.Printf("System tx\n") - return - } - } txHash := txTask.Tx.Hash() rw.taskGasPool.Reset(txTask.Tx.GetGas()) rw.callTracer.Reset() diff --git a/cmd/state/exec3/state_recon.go b/cmd/state/exec3/state_recon.go index 3ca57a7a6..750363e28 100644 --- a/cmd/state/exec3/state_recon.go +++ b/cmd/state/exec3/state_recon.go @@ -7,13 +7,14 @@ import ( "sync" "github.com/RoaringBitmap/roaring/roaring64" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/length" "github.com/ledgerwatch/erigon-lib/etl" "github.com/ledgerwatch/erigon-lib/kv" libstate "github.com/ledgerwatch/erigon-lib/state" - "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon/cmd/state/exec22" "github.com/ledgerwatch/erigon/common" @@ -21,7 +22,6 @@ import ( "github.com/ledgerwatch/erigon/consensus/misc" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/state" - "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/core/types/accounts" "github.com/ledgerwatch/erigon/core/vm" @@ -231,8 +231,6 @@ type ReconWorker struct { logger log.Logger genesis *types.Genesis chain ChainReader - isPoSA bool - posa consensus.PoSA evm *vm.EVM ibs *state.IntraBlockState @@ -258,7 +256,6 @@ func NewReconWorker(lock sync.Locker, ctx context.Context, rs *state.ReconState, } rw.chain = NewChainReader(chainConfig, chainTx, blockReader) rw.ibs = state.New(rw.stateReader) - rw.posa, rw.isPoSA = engine.(consensus.PoSA) return rw } @@ -325,24 +322,12 @@ func (rw *ReconWorker) runTxTask(txTask *exec22.TxTask) error { } } else if txTask.TxIndex == -1 { // Block initialisation - if rw.isPoSA { - systemcontracts.UpgradeBuildInSystemContract(rw.chainConfig, txTask.Header.Number, ibs) - } syscall := func(contract libcommon.Address, data []byte) ([]byte, error) { return core.SysCallContract(contract, data, *rw.chainConfig, ibs, txTask.Header, rw.engine, false /* constCall */, nil /*excessDataGas*/) } rw.engine.Initialize(rw.chainConfig, rw.chain, txTask.Header, ibs, txTask.Txs, txTask.Uncles, syscall) } else { - if rw.isPoSA { - if isSystemTx, err := rw.posa.IsSystemTransaction(txTask.Tx, txTask.Header); err != nil { - if _, readError := rw.stateReader.ReadError(); !readError { - return err - } - } else if isSystemTx { - return nil - } - } gp := new(core.GasPool).AddGas(txTask.Tx.GetGas()) vmConfig := vm.Config{NoReceipts: true, SkipAnalysis: txTask.SkipAnalysis} ibs.Prepare(txTask.Tx.Hash(), txTask.BlockHash, txTask.TxIndex) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 7944a5eca..f6e5e33d9 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -129,7 +129,7 @@ var ( } SnapshotFlag = cli.BoolFlag{ Name: "snapshots", - Usage: `Default: use snapshots "true" for BSC, Mainnet and Goerli. use snapshots "false" in all other cases`, + Usage: `Default: use snapshots "true" for Mainnet, Goerli, Gnosis Chain and Chiado. use snapshots "false" in all other cases`, Value: true, } ExternalConsensusFlag = cli.BoolFlag{ @@ -1346,10 +1346,6 @@ func setAuRa(ctx *cli.Context, cfg *chain.AuRaConfig, datadir string) { cfg.DBPath = filepath.Join(datadir, "aura") } -func setParlia(ctx *cli.Context, cfg *chain.ParliaConfig, datadir string) { - cfg.DBPath = filepath.Join(datadir, "parlia") -} - func setBorConfig(ctx *cli.Context, cfg *ethconfig.Config) { cfg.HeimdallURL = ctx.String(HeimdallURLFlag.Name) cfg.WithoutHeimdall = ctx.Bool(WithoutHeimdallFlag.Name) @@ -1505,7 +1501,6 @@ func SetEthConfig(ctx *cli.Context, nodeConfig *nodecfg.Config, cfg *ethconfig.C setEthash(ctx, nodeConfig.Dirs.DataDir, cfg) setClique(ctx, &cfg.Clique, nodeConfig.Dirs.DataDir) setAuRa(ctx, &cfg.Aura, nodeConfig.Dirs.DataDir) - setParlia(ctx, &cfg.Parlia, nodeConfig.Dirs.DataDir) setMiner(ctx, &cfg.Miner) setWhitelist(ctx, cfg) setBorConfig(ctx, cfg) diff --git a/consensus/consensus.go b/consensus/consensus.go index 829c27517..77939fb6a 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -18,7 +18,6 @@ package consensus import ( - "context" "math/big" "github.com/ledgerwatch/erigon-lib/chain" @@ -152,23 +151,3 @@ type PoW interface { // Hashrate returns the current mining hashrate of a PoW consensus engine. Hashrate() float64 } - -var ( - SystemAddress = libcommon.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") -) - -type PoSA interface { - Engine - - IsSystemTransaction(tx types.Transaction, header *types.Header) (bool, error) - IsSystemContract(to *libcommon.Address) bool - EnoughDistance(chain ChainReader, header *types.Header) bool - IsLocalBlock(header *types.Header) bool - AllowLightProcess(chain ChainReader, currentHeader *types.Header) bool -} - -type AsyncEngine interface { - Engine - - WithExecutionContext(context.Context) AsyncEngine -} diff --git a/consensus/parlia/abi.go b/consensus/parlia/abi.go deleted file mode 100644 index e841eb5cd..000000000 --- a/consensus/parlia/abi.go +++ /dev/null @@ -1,1525 +0,0 @@ -package parlia - -const validatorSetABI = ` -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "batchTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "batchTransferFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "batchTransferLowerFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "deprecatedDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address payable", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "directTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address payable", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "directTransferFail", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "failReasonWithStr", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "feeBurned", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "systemTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "unexpectedPackage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "validatorDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "validatorEmptyJailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "validatorEnterMaintenance", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "validatorExitMaintenance", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "validatorFelony", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "validatorJailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "validatorMisdemeanor", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "validatorSetUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "BURN_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "BURN_RATIO_SCALE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DUSTY_INCOMING", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "EPOCH", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ERROR_FAIL_CHECK_VALIDATORS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ERROR_LEN_OF_VAL_MISMATCH", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ERROR_RELAYFEE_TOO_LARGE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ERROR_UNKNOWN_PACKAGE_TYPE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "EXPIRE_TIME_SECOND_GAP", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INIT_BURN_RATIO", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INIT_MAINTAIN_SLASH_SCALE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INIT_MAX_NUM_OF_MAINTAINING", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INIT_NUM_OF_CABINETS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INIT_VALIDATORSET_BYTES", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "JAIL_MESSAGE_TYPE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_OF_VALIDATORS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PRECISION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SYSTEM_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATORS_UPDATE_MESSAGE_TYPE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "burnRatio", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "burnRatioInitialized", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "currentValidatorSet", - "outputs": [ - { - "internalType": "address", - "name": "consensusAddress", - "type": "address" - }, - { - "internalType": "address payable", - "name": "feeAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "BBCFeeAddress", - "type": "address" - }, - { - "internalType": "uint64", - "name": "votingPower", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "jailed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "incoming", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "currentValidatorSetMap", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "expireTimeSecondGap", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maintainSlashScale", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxNumOfCandidates", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxNumOfMaintaining", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxNumOfWorkingCandidates", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "numOfCabinets", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "numOfJailed", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "numOfMaintaining", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalInComing", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "valAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "slashAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "rewardAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "lightAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenHubAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "incentivizeAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "relayerHubAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "govHub", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenManagerAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "crossChain", - "type": "address" - } - ], - "name": "updateContractAddr", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "validatorExtraSet", - "outputs": [ - { - "internalType": "uint256", - "name": "enterMaintenanceHeight", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "isMaintaining", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "init", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleSynPackage", - "outputs": [ - { - "internalType": "bytes", - "name": "responsePayload", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleAckPackage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleFailAckPackage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "valAddr", - "type": "address" - } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "getMiningValidators", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getValidators", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "isWorkingValidator", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "getIncoming", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "isCurrentValidator", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "misdemeanor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "felony", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_validator", - "type": "address" - } - ], - "name": "getCurrentValidatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "canEnterMaintenance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "enterMaintenance", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "exitMaintenance", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "updateParam", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "isValidatorExist", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMaintainingValidators", - "outputs": [ - { - "internalType": "address[]", - "name": "maintainingValidators", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - } - ] -` - -const slashABI = ` -[ - { - "anonymous": false, - "inputs": [], - "name": "indicatorCleaned", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "validatorSlashed", - "type": "event" - }, - { - "inputs": [], - "name": "FELONY_THRESHOLD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MISDEMEANOR_THRESHOLD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SYSTEM_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "previousHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "slash", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "clean", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "getSlashIndicator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } - ] -` diff --git a/consensus/parlia/api.go b/consensus/parlia/api.go deleted file mode 100644 index 066414abd..000000000 --- a/consensus/parlia/api.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package parlia - -import ( - libcommon "github.com/ledgerwatch/erigon-lib/common" - - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/rpc" -) - -// API is a user facing RPC API to allow query snapshot and validators -type API struct { - chain consensus.ChainHeaderReader - parlia *Parlia -} - -// GetSnapshot retrieves the state snapshot at a given block. -func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { - // Retrieve the requested block number (or current if none requested) - var header *types.Header - if number == nil || *number == rpc.LatestBlockNumber { - header = api.chain.CurrentHeader() - } else { - header = api.chain.GetHeaderByNumber(uint64(number.Int64())) - } - // Ensure we have an actually valid block and return its snapshot - if header == nil { - return nil, errUnknownBlock - } - return api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil, false /* verify */) -} - -// GetSnapshotAtHash retrieves the state snapshot at a given block. -func (api *API) GetSnapshotAtHash(hash libcommon.Hash) (*Snapshot, error) { - header := api.chain.GetHeaderByHash(hash) - if header == nil { - return nil, errUnknownBlock - } - return api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil, false /* verify */) -} - -// GetValidators retrieves the list of validators at the specified block. -func (api *API) GetValidators(number *rpc.BlockNumber) ([]libcommon.Address, error) { - // Retrieve the requested block number (or current if none requested) - var header *types.Header - if number == nil || *number == rpc.LatestBlockNumber { - header = api.chain.CurrentHeader() - } else { - header = api.chain.GetHeaderByNumber(uint64(number.Int64())) - } - // Ensure we have an actually valid block and return the validators from its snapshot - if header == nil { - return nil, errUnknownBlock - } - snap, err := api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil, false /* verify */) - if err != nil { - return nil, err - } - return snap.validators(), nil -} - -// GetValidatorsAtHash retrieves the list of validators at the specified block. -func (api *API) GetValidatorsAtHash(hash libcommon.Hash) ([]libcommon.Address, error) { - header := api.chain.GetHeaderByHash(hash) - if header == nil { - return nil, errUnknownBlock - } - snap, err := api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil, false /* verify */) - if err != nil { - return nil, err - } - return snap.validators(), nil -} diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go deleted file mode 100644 index 67c97f7a5..000000000 --- a/consensus/parlia/parlia.go +++ /dev/null @@ -1,1278 +0,0 @@ -package parlia - -import ( - "bytes" - "context" - "encoding/hex" - "errors" - "fmt" - "io" - "math/big" - "sort" - "strings" - "sync" - "time" - - lru "github.com/hashicorp/golang-lru/v2" - "github.com/holiman/uint256" - "github.com/ledgerwatch/log/v3" - "golang.org/x/exp/slices" - - "github.com/ledgerwatch/erigon-lib/chain" - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon-lib/common/hexutility" - "github.com/ledgerwatch/erigon-lib/common/length" - "github.com/ledgerwatch/erigon-lib/kv" - - "github.com/ledgerwatch/erigon/accounts/abi" - "github.com/ledgerwatch/erigon/common/math" - "github.com/ledgerwatch/erigon/common/u256" - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/misc" - "github.com/ledgerwatch/erigon/core" - "github.com/ledgerwatch/erigon/core/forkid" - "github.com/ledgerwatch/erigon/core/rawdb" - "github.com/ledgerwatch/erigon/core/state" - "github.com/ledgerwatch/erigon/core/systemcontracts" - "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/core/vm" - "github.com/ledgerwatch/erigon/crypto" - "github.com/ledgerwatch/erigon/crypto/cryptopool" - "github.com/ledgerwatch/erigon/params" - "github.com/ledgerwatch/erigon/rlp" - "github.com/ledgerwatch/erigon/rpc" - "github.com/ledgerwatch/erigon/turbo/snapshotsync" -) - -const ( - inMemorySnapshots = 128 // Number of recent snapshots to keep in memory - inMemorySignatures = 4096 // Number of recent block signatures to keep in memory - - CheckpointInterval = 1024 // Number of blocks after which to save the snapshot to the database - defaultEpochLength = uint64(100) // Default number of blocks of checkpoint to update validatorSet from contract - - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity - extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal - nextForkHashSize = 4 // Fixed number of extra-data suffix bytes reserved for nextForkHash. - - validatorBytesLength = length.Addr - wiggleTime = uint64(1) // second, Random delay (per signer) to allow concurrent signers - initialBackOffTime = uint64(1) // second - processBackOffTime = uint64(1) // second - - systemRewardPercent = 4 // it means 1/2^4 = 1/16 percentage of gas fee incoming will be distributed to system -) - -var ( - uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. - diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures - diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures - // 100 native token - maxSystemBalance = new(uint256.Int).Mul(uint256.NewInt(100), uint256.NewInt(params.Ether)) - - systemContracts = map[libcommon.Address]struct{}{ - systemcontracts.ValidatorContract: {}, - systemcontracts.SlashContract: {}, - systemcontracts.SystemRewardContract: {}, - systemcontracts.LightClientContract: {}, - systemcontracts.RelayerHubContract: {}, - systemcontracts.GovHubContract: {}, - systemcontracts.TokenHubContract: {}, - systemcontracts.RelayerIncentivizeContract: {}, - systemcontracts.CrossChainContract: {}, - } -) - -// Various error messages to mark blocks invalid. These should be private to -// prevent engine specific errors from being referenced in the remainder of the -// codebase, inherently breaking if the engine is swapped out. Please put common -// error types into the consensus package. -var ( - // errUnknownBlock is returned when the list of validators is requested for a block - // that is not part of the local blockchain. - errUnknownBlock = errors.New("unknown block") - - // errMissingVanity is returned if a block's extra-data section is shorter than - // 32 bytes, which is required to store the signer vanity. - errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") - - // errMissingSignature is returned if a block's extra-data section doesn't seem - // to contain a 65 byte secp256k1 signature. - errMissingSignature = errors.New("extra-data 65 byte signature suffix missing") - - // errExtraValidators is returned if non-sprint-end block contain validator data in - // their extra-data fields. - errExtraValidators = errors.New("non-sprint-end block contains extra validator list") - - // errInvalidSpanValidators is returned if a block contains an - // invalid list of validators (i.e. non divisible by 20 bytes). - errInvalidSpanValidators = errors.New("invalid validator list on sprint end block") - - // errInvalidMixDigest is returned if a block's mix digest is non-zero. - errInvalidMixDigest = errors.New("non-zero mix digest") - - // errInvalidUncleHash is returned if a block contains an non-empty uncle list. - errInvalidUncleHash = errors.New("non empty uncle hash") - - // errMismatchingEpochValidators is returned if a sprint block contains a - // list of validators different than the one the local node calculated. - errMismatchingEpochValidators = errors.New("mismatching validator list on epoch block") - - // errInvalidDifficulty is returned if the difficulty of a block is missing. - errInvalidDifficulty = errors.New("invalid difficulty") - - // errWrongDifficulty is returned if the difficulty of a block doesn't match the - // turn of the signer. - errWrongDifficulty = errors.New("wrong difficulty") - - // errOutOfRangeChain is returned if an authorization list is attempted to - // be modified via out-of-range or non-contiguous headers. - errOutOfRangeChain = errors.New("out of range or non-contiguous chain") - - // errBlockHashInconsistent is returned if an authorization list is attempted to - // insert an inconsistent block. - errBlockHashInconsistent = errors.New("the block hash is inconsistent") - - // errUnauthorizedValidator is returned if a header is signed by a non-authorized entity. - errUnauthorizedValidator = errors.New("unauthorized validator") - - // errCoinBaseMisMatch is returned if a header's coinbase do not match with signature - errCoinBaseMisMatch = errors.New("coinbase do not match with signature") - - // errRecentlySigned is returned if a header is signed by an authorized entity - // that already signed a header recently, thus is temporarily not allowed to. - errRecentlySigned = errors.New("recently signed") -) - -// SignFn is a signer callback function to request a header to be signed by a -// backing account. -type SignFn func(validator libcommon.Address, payload []byte, chainId *big.Int) ([]byte, error) - -// ecrecover extracts the Ethereum account address from a signed header. -func ecrecover(header *types.Header, sigCache *lru.ARCCache[libcommon.Hash, libcommon.Address], chainId *big.Int) (libcommon.Address, error) { - // If the signature's already cached, return that - hash := header.Hash() - if address, known := sigCache.Get(hash); known { - return address, nil - } - // Retrieve the signature from the header extra-data - if len(header.Extra) < extraSeal { - return libcommon.Address{}, errMissingSignature - } - signature := header.Extra[len(header.Extra)-extraSeal:] - - // Recover the public key and the Ethereum address - pubkey, err := crypto.Ecrecover(SealHash(header, chainId).Bytes(), signature) - if err != nil { - return libcommon.Address{}, err - } - var signer libcommon.Address - copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) - - sigCache.Add(hash, signer) - return signer, nil -} - -// SealHash returns the hash of a block prior to it being sealed. -func SealHash(header *types.Header, chainId *big.Int) (hash libcommon.Hash) { - hasher := cryptopool.NewLegacyKeccak256() - defer cryptopool.ReturnToPoolKeccak256(hasher) - - encodeSigHeader(hasher, header, chainId) - hasher.Sum(hash[:0]) - return hash -} - -func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) { - err := rlp.Encode(w, []interface{}{ - chainId, - header.ParentHash, - header.UncleHash, - header.Coinbase, - header.Root, - header.TxHash, - header.ReceiptHash, - header.Bloom, - header.Difficulty, - header.Number, - header.GasLimit, - header.GasUsed, - header.Time, - header.Extra[:len(header.Extra)-65], // this will panic if extra is too short, should check before calling encodeSigHeader - header.MixDigest, - header.Nonce, - }) - if err != nil { - panic("can't encode: " + err.Error()) - } -} - -// parliaRLP returns the rlp bytes which needs to be signed for the parlia -// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature -// contained at the end of the extra data. -// -// Note, the method requires the extra data to be at least 65 bytes, otherwise it -// panics. This is done to avoid accidentally using both forms (signature present -// or not), which could be abused to produce different hashes for the same header. -func parliaRLP(header *types.Header, chainId *big.Int) []byte { - b := new(bytes.Buffer) - encodeSigHeader(b, header, chainId) - return b.Bytes() -} - -type Parlia struct { - chainConfig *chain.Config // Chain config - config *chain.ParliaConfig // Consensus engine configuration parameters for parlia consensus - genesisHash libcommon.Hash - db kv.RwDB // Database to store and retrieve snapshot checkpoints - chainDb kv.RwDB - - recentSnaps *lru.ARCCache[libcommon.Hash, *Snapshot] // Snapshots for recent block to speed up - signatures *lru.ARCCache[libcommon.Hash, libcommon.Address] // Signatures of recent blocks to speed up mining - - signer *types.Signer - - val libcommon.Address // Ethereum address of the signing key - signFn SignFn // Signer function to authorize hashes with - - signerLock sync.RWMutex // Protects the signer fields - - snapLock sync.RWMutex // Protects snapshots creation - - validatorSetABI abi.ABI - slashABI abi.ABI - - // The fields below are for testing only - fakeDiff bool // Skip difficulty verifications - heightForks, timeForks []uint64 // Forks extracted from the chainConfig - snapshots *snapshotsync.RoSnapshots -} - -// New creates a Parlia consensus engine. -func New( - chainConfig *chain.Config, - db kv.RwDB, - snapshots *snapshotsync.RoSnapshots, - chainDb kv.RwDB, -) *Parlia { - // get parlia config - parliaConfig := chainConfig.Parlia - - // Set any missing consensus parameters to their defaults - if parliaConfig != nil && parliaConfig.Epoch == 0 { - parliaConfig.Epoch = defaultEpochLength - } - - // Allocate the snapshot caches and create the engine - recentSnaps, err := lru.NewARC[libcommon.Hash, *Snapshot](inMemorySnapshots) - if err != nil { - panic(err) - } - signatures, err := lru.NewARC[libcommon.Hash, libcommon.Address](inMemorySignatures) - if err != nil { - panic(err) - } - vABI, err := abi.JSON(strings.NewReader(validatorSetABI)) - if err != nil { - panic(err) - } - sABI, err := abi.JSON(strings.NewReader(slashABI)) - if err != nil { - panic(err) - } - c := &Parlia{ - chainConfig: chainConfig, - config: parliaConfig, - db: db, - chainDb: chainDb, - recentSnaps: recentSnaps, - signatures: signatures, - validatorSetABI: vABI, - slashABI: sABI, - signer: types.LatestSigner(chainConfig), - snapshots: snapshots, - } - c.heightForks, c.timeForks = forkid.GatherForks(chainConfig) - - return c -} - -// Type returns underlying consensus engine -func (p *Parlia) Type() chain.ConsensusName { - return chain.ParliaConsensus -} - -// Author retrieves the Ethereum address of the account that minted the given -// block, which may be different from the header's coinbase if a consensus -// engine is based on signatures. -// This is thread-safe (only access the header.Coinbase) -func (p *Parlia) Author(header *types.Header) (libcommon.Address, error) { - return header.Coinbase, nil -} - -// VerifyHeader checks whether a header conforms to the consensus rules of a -// given engine. Verifying the seal may be done optionally here, or explicitly -// via the VerifySeal method. -func (p *Parlia) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { - return p.verifyHeader(chain, header, nil) -} - -// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers -// concurrently. The method returns a quit channel to abort the operations and -// a results channel to retrieve the async verifications (the order is that of -// the input slice). -func (p *Parlia) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) error { - for i, header := range headers { - err := p.verifyHeader(chain, header, headers[:i]) - if err != nil { - return err - } - } - return nil -} - -// verifyHeader checks whether a header conforms to the consensus rules.The -// caller may optionally pass in a batch of parents (ascending order) to avoid -// looking those up from the database. This is useful for concurrently verifying -// a batch of new headers. -func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { - if header.Number == nil { - return errUnknownBlock - } - number := header.Number.Uint64() - - // Don't waste time checking blocks from the future - if header.Time > uint64(time.Now().Unix()) { - return fmt.Errorf("header %d, time %d, now %d, %w", header.Number.Uint64(), header.Time, time.Now().Unix(), consensus.ErrFutureBlock) - } - // Check that the extra-data contains the vanity, validators and signature. - if len(header.Extra) < extraVanity { - return errMissingVanity - } - if len(header.Extra) < extraVanity+extraSeal { - return errMissingSignature - } - // check extra data - isEpoch := number%p.config.Epoch == 0 - - // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise - signersBytes := len(header.Extra) - extraVanity - extraSeal - if !isEpoch && signersBytes != 0 { - return errExtraValidators - } - - if isEpoch && signersBytes%validatorBytesLength != 0 { - return errInvalidSpanValidators - } - - // Ensure that the mix digest is zero as we don't have fork protection currently - if header.MixDigest != (libcommon.Hash{}) { - return errInvalidMixDigest - } - // Ensure that the block doesn't contain any uncles which are meaningless in PoA - if header.UncleHash != uncleHash { - return errInvalidUncleHash - } - // Ensure that the block's difficulty is meaningful (may not be correct at this point) - if number > 0 { - if header.Difficulty == nil { - return errInvalidDifficulty - } - } - - if header.WithdrawalsHash != nil { - return consensus.ErrUnexpectedWithdrawals - } - - // All basic checks passed, verify cascading fields - return p.verifyCascadingFields(chain, header, parents) -} - -// verifyCascadingFields verifies all the header fields that are not standalone, -// rather depend on a batch of previous headers. The caller may optionally pass -// in a batch of parents (ascending order) to avoid looking those up from the -// database. This is useful for concurrently verifying a batch of new headers. -func (p *Parlia) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { - // The genesis block is the always valid dead-end - number := header.Number.Uint64() - if number == 0 { - return nil - } - - var parent *types.Header - if len(parents) > 0 { - parent = parents[len(parents)-1] - } else { - parent = chain.GetHeader(header.ParentHash, number-1) - } - - if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { - return consensus.ErrUnknownAncestor - } - - snap, err := p.snapshot(chain, number-1, header.ParentHash, parents, true /* verify */) - if err != nil { - return err - } - - err = p.blockTimeVerifyForRamanujanFork(snap, header, parent) - if err != nil { - return err - } - - // Verify that the gas limit is <= 2^63-1 - capacity := uint64(0x7fffffffffffffff) - if header.GasLimit > capacity { - return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, capacity) - } - // Verify that the gasUsed is <= gasLimit - if header.GasUsed > header.GasLimit { - return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) - } - - // Verify that the gas limit remains within allowed bounds - diff := int64(parent.GasLimit) - int64(header.GasLimit) - if diff < 0 { - diff *= -1 - } - limit := parent.GasLimit / params.GasLimitBoundDivisor - - if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { - return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) - } - - // All basic checks passed, verify the seal and return - return p.verifySeal(chain, header, parents) -} - -// verifySeal checks whether the signature contained in the header satisfies the -// consensus protocol requirements. The method accepts an optional list of parent -// headers that aren't yet part of the local blockchain to generate the snapshots -// from. -func (p *Parlia) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { - // Verifying the genesis block is not supported - number := header.Number.Uint64() - if number == 0 { - return errUnknownBlock - } - // Retrieve the snapshot needed to verify this header and cache it - snap, err := p.snapshot(chain, number-1, header.ParentHash, parents, true /* verify */) - if err != nil { - return err - } - - // Resolve the authorization key and check against validators - signer, err := ecrecover(header, p.signatures, p.chainConfig.ChainID) - if err != nil { - return err - } - - if signer != header.Coinbase { - return errCoinBaseMisMatch - } - - if _, ok := snap.Validators[signer]; !ok { - return fmt.Errorf("parlia.verifySeal: headerNum=%d, validator=%x, %w", header.Number.Uint64(), signer.Bytes(), errUnauthorizedValidator) - } - - for seen, recent := range snap.Recents { - if recent == signer { - // Signer is among recents, only fail if the current block doesn't shift it out - if limit := uint64(len(snap.Validators)/2 + 1); seen > number-limit { - return errRecentlySigned - } - } - } - - // Ensure that the difficulty corresponds to the turn-ness of the signer - if !p.fakeDiff { - inturn := snap.inturn(signer) - if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { - return errWrongDifficulty - } - if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 { - return errWrongDifficulty - } - } - - return nil -} - -// snapshot retrieves the authorization snapshot at a given point in time. -func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash libcommon.Hash, parents []*types.Header, verify bool) (*Snapshot, error) { - // Search for a snapshot in memory or on disk for checkpoints - var ( - headers []*types.Header - snap *Snapshot - doLog bool - ) - - if s, ok := p.recentSnaps.Get(hash); ok { - snap = s - } else { - p.snapLock.Lock() - defer p.snapLock.Unlock() - doLog = true - } - - for snap == nil { - // If an in-memory snapshot was found, use that - if s, ok := p.recentSnaps.Get(hash); ok { - snap = s - break - } - - // If an on-disk checkpoint snapshot can be found, use that - if number%CheckpointInterval == 0 { - if s, err := loadSnapshot(p.config, p.signatures, p.db, number, hash); err == nil { - //log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) - snap = s - if !verify || snap != nil { - break - } - } - } - if number == 0 { - // Headers included into the snapshots have to be trusted as checkpoints - checkpoint := chain.GetHeader(hash, number) - if checkpoint != nil { - validatorBytes := checkpoint.Extra[extraVanity : len(checkpoint.Extra)-extraSeal] - // get validators from headers - validators, err := ParseValidators(validatorBytes) - if err != nil { - return nil, err - } - // new snapshot - snap = newSnapshot(p.config, p.signatures, number, hash, validators) - if err := snap.store(p.db); err != nil { - return nil, err - } - break - } - } - - // No snapshot for this header, gather the header and move backward - var header *types.Header - if len(parents) > 0 { - // If we have explicit parents, pick from there (enforced) - header = parents[len(parents)-1] - if header.Hash() != hash || header.Number.Uint64() != number { - return nil, consensus.ErrUnknownAncestor - } - parents = parents[:len(parents)-1] - } else { - if doLog && number%100_000 == 0 { - // No explicit parents (or no more left), reach out to the database - log.Info("[parlia] snapshots build, gather headers", "block", number) - } - header = chain.GetHeader(hash, number) - if header == nil { - return nil, consensus.ErrUnknownAncestor - } - } - headers = append(headers, header) - number, hash = number-1, header.ParentHash - } - - // check if snapshot is nil - if snap == nil { - return nil, fmt.Errorf("unknown error while retrieving snapshot at block number %v", number) - } - - // Previous snapshot found, apply any pending headers on top of it - for i := 0; i < len(headers)/2; i++ { - headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] - } - snap, err := snap.apply(headers, chain, parents, p.chainConfig.ChainID, doLog) - if err != nil { - return nil, err - } - p.recentSnaps.Add(snap.Hash, snap) - - // If we've generated a new checkpoint snapshot, save to disk - if verify && snap.Number%CheckpointInterval == 0 && len(headers) > 0 { - if err = snap.store(p.db); err != nil { - return nil, err - } - //log.Trace("Stored snapshot to disk", "number", snap.Number, "hash", snap.Hash) - } - return snap, err -} - -// VerifyUncles verifies that the given block's uncles conform to the consensus -// rules of a given engine. -func (p *Parlia) VerifyUncles(chain consensus.ChainReader, header *types.Header, uncles []*types.Header) error { - if len(uncles) > 0 { - return errors.New("uncles not allowed") - } - return nil -} - -// Prepare initializes the consensus fields of a block header according to the -// rules of a particular engine. The changes are executed inline. -func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header, ibs *state.IntraBlockState) error { - header.Coinbase = p.val - header.Nonce = types.BlockNonce{} - - number := header.Number.Uint64() - snap, err := p.snapshot(chain, number-1, header.ParentHash, nil, false /* verify */) - if err != nil { - return err - } - - parent := chain.GetHeader(header.ParentHash, number-1) - if parent == nil { - return consensus.ErrUnknownAncestor - } - - // Set the correct difficulty - header.Difficulty = CalcDifficulty(snap, p.val) - - // Ensure the timestamp has the correct delay - header.Time = p.blockTimeForRamanujanFork(snap, header, parent) - if header.Time < uint64(time.Now().Unix()) { - header.Time = uint64(time.Now().Unix()) - } - - // Ensure the extra data has all it's components - if len(header.Extra) < extraVanity-nextForkHashSize { - header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-nextForkHashSize-len(header.Extra))...) - } - header.Extra = header.Extra[:extraVanity-nextForkHashSize] - nextForkHash := forkid.NextForkHashFromForks(p.heightForks, p.timeForks, p.genesisHash, number, header.Time) - header.Extra = append(header.Extra, nextForkHash[:]...) - - if number%p.config.Epoch == 0 { - newValidators, err := p.getCurrentValidators(parent, ibs) - if err != nil { - return err - } - // sort validator by address - sort.Sort(validatorsAscending(newValidators)) - for _, validator := range newValidators { - header.Extra = append(header.Extra, validator.Bytes()...) - } - } - - // add extra seal space - header.Extra = append(header.Extra, make([]byte, extraSeal)...) - - // Mix digest is reserved for now, set to empty - header.MixDigest = libcommon.Hash{} - - return nil -} - -// Initialize runs any pre-transaction state modifications (e.g. epoch start) -func (p *Parlia) Initialize(config *chain.Config, chain consensus.ChainHeaderReader, header *types.Header, - state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, syscall consensus.SystemCall) { -} - -func (p *Parlia) splitTxs(txs types.Transactions, header *types.Header) (userTxs types.Transactions, systemTxs types.Transactions, err error) { - userTxs = types.Transactions{} - systemTxs = types.Transactions{} - for _, tx := range txs { - isSystemTx, err2 := p.IsSystemTransaction(tx, header) - if err2 != nil { - err = err2 - return - } - if isSystemTx { - systemTxs = append(systemTxs, tx) - } else { - userTxs = append(userTxs, tx) - } - } - return -} - -// Finalize runs any post-transaction state modifications (e.g. block rewards) -// but does not assemble the block. -// -// Note: The block header and state database might be updated to reflect any -// consensus rules that happen at finalization (e.g. block rewards). -func (p *Parlia) Finalize(_ *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, _ []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, - chain consensus.ChainHeaderReader, syscall consensus.SystemCall, -) (types.Transactions, types.Receipts, error) { - return p.finalize(header, state, txs, receipts, chain, false) -} - -func (p *Parlia) finalize(header *types.Header, state *state.IntraBlockState, txs types.Transactions, - receipts types.Receipts, chain consensus.ChainHeaderReader, mining bool, -) (types.Transactions, types.Receipts, error) { - userTxs, systemTxs, err := p.splitTxs(txs, header) - if err != nil { - return nil, nil, err - } - txs = userTxs - // warn if not in majority fork - number := header.Number.Uint64() - snap, err := p.snapshot(chain, number-1, header.ParentHash, nil, false /* verify */) - if err != nil { - return nil, nil, err - } - /* - nextForkHash := forkid.NextForkHashFromForks(p.forks, p.genesisHash, number) - nextForkHashStr := hex.EncodeToString(nextForkHash[:]) - if !snap.isMajorityFork(nextForkHashStr) { - log.Debug("[parlia] there is a possible fork, and your client is not the majority. Please check...", "nextForkHash", nextForkHashStr) - } - */ - // If the block is an epoch end block, verify the validator list - // The verification can only be done when the state is ready, it can't be done in VerifyHeader. - if number%p.config.Epoch == 0 { - parentHeader := chain.GetHeader(header.ParentHash, number-1) - newValidators, err := p.getCurrentValidators(parentHeader, state) - if err != nil { - return nil, nil, err - } - // sort validator by address - sort.Sort(validatorsAscending(newValidators)) - validatorsBytes := make([]byte, len(newValidators)*validatorBytesLength) - for i, validator := range newValidators { - copy(validatorsBytes[i*validatorBytesLength:], validator.Bytes()) - } - - extraSuffix := len(header.Extra) - extraSeal - if !bytes.Equal(header.Extra[extraVanity:extraSuffix], validatorsBytes) { - return nil, nil, errMismatchingEpochValidators - } - } - // No block rewards in PoA, so the state remains as is and uncles are dropped - if number == 1 { - var err error - if txs, systemTxs, receipts, err = p.initContract(state, header, txs, receipts, systemTxs, &header.GasUsed, mining); err != nil { - log.Error("[parlia] init contract failed", "err", err) - return nil, nil, fmt.Errorf("init contract failed: %v", err) - } - } - if header.Difficulty.Cmp(diffInTurn) != 0 { - spoiledVal := snap.supposeValidator() - signedRecently := false - for _, recent := range snap.Recents { - if recent == spoiledVal { - signedRecently = true - break - } - } - if !signedRecently { - //log.Trace("slash validator", "block hash", header.Hash(), "address", spoiledVal) - var tx types.Transaction - var receipt *types.Receipt - if systemTxs, tx, receipt, err = p.slash(spoiledVal, state, header, len(txs), systemTxs, &header.GasUsed, mining); err != nil { - // it is possible that slash validator failed because of the slash channel is disabled. - log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal, "error", err) - } else { - txs = append(txs, tx) - receipts = append(receipts, receipt) - log.Debug("slash successful", "txns", txs.Len(), "receipts", len(receipts), "gasUsed", header.GasUsed) - } - } - } - if txs, systemTxs, receipts, err = p.distributeIncoming(header.Coinbase, state, header, txs, receipts, systemTxs, &header.GasUsed, mining); err != nil { - //log.Error("distributeIncoming", "block hash", header.Hash(), "error", err, "systemTxs", len(systemTxs)) - return nil, nil, err - } - //log.Debug("distribute successful", "txns", txs.Len(), "receipts", len(receipts), "gasUsed", header.GasUsed) - if len(systemTxs) > 0 { - return nil, nil, fmt.Errorf("the length of systemTxs is still %d", len(systemTxs)) - } - // Re-order receipts so that are in right order - slices.SortFunc(receipts, func(a, b *types.Receipt) bool { return a.TransactionIndex < b.TransactionIndex }) - return txs, receipts, nil -} - -// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block -// rewards) and assembles the final block. -// -// Note: The block header and state database might be updated to reflect any -// consensus rules that happen at finalization (e.g. block rewards). -func (p *Parlia) FinalizeAndAssemble(_ *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, _ []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, - chain consensus.ChainHeaderReader, syscall consensus.SystemCall, call consensus.Call, -) (*types.Block, types.Transactions, types.Receipts, error) { - outTxs, outReceipts, err := p.finalize(header, state, txs, receipts, chain, true) - if err != nil { - return nil, nil, nil, err - } - return types.NewBlock(header, outTxs, nil, outReceipts, withdrawals), outTxs, outReceipts, nil -} - -// Authorize injects a private key into the consensus engine to mint new blocks -// with. -func (p *Parlia) Authorize(val libcommon.Address, signFn SignFn) { - p.signerLock.Lock() - defer p.signerLock.Unlock() - - p.val = val - p.signFn = signFn -} - -// Seal generates a new sealing request for the given input block and pushes -// the result into the given channel. -// -// Note, the method returns immediately and will send the result async. More -// than one result may also be returned depending on the consensus algorithm. -func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - header := block.Header() - - // Sealing the genesis block is not supported - number := header.Number.Uint64() - if number == 0 { - return errUnknownBlock - } - // For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) - if p.config.Period == 0 && len(block.Transactions()) == 0 { - log.Info("[parlia] Sealing paused, waiting for transactions") - return nil - } - // Don't hold the val fields for the entire sealing procedure - p.signerLock.RLock() - val, signFn := p.val, p.signFn - p.signerLock.RUnlock() - - snap, err := p.snapshot(chain, number-1, header.ParentHash, nil, false /* verify */) - if err != nil { - return err - } - - // Bail out if we're unauthorized to sign a block - if _, authorized := snap.Validators[val]; !authorized { - return fmt.Errorf("parlia.Seal: %w", errUnauthorizedValidator) - } - - // If we're amongst the recent signers, wait for the next block - for seen, recent := range snap.Recents { - if recent == val { - // Signer is among recent, only wait if the current block doesn't shift it out - if limit := uint64(len(snap.Validators)/2 + 1); number < limit || seen > number-limit { - log.Info("[parlia] Signed recently, must wait for others") - return nil - } - } - } - - // Sweet, the protocol permits us to sign the block, wait for our time - delay := p.delayForRamanujanFork(snap, header) - - log.Info("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "val", val.Hex(), "headerHash", header.Hash().Hex(), "gasUsed", header.GasUsed, "block txn number", block.Transactions().Len(), "State Root", header.Root) - - // Sign all the things! - sig, err := signFn(val, crypto.Keccak256(parliaRLP(header, p.chainConfig.ChainID)), p.chainConfig.ChainID) - if err != nil { - return err - } - copy(header.Extra[len(header.Extra)-extraSeal:], sig) - - // Wait until sealing is terminated or delay timeout. - //log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) - go func() { - select { - case <-stop: - return - case <-time.After(delay): - } - if p.shouldWaitForCurrentBlockProcess(p.chainDb, header, snap) { - log.Info("[parlia] Waiting for received in turn block to process") - select { - case <-stop: - log.Info("[parlia] Received block process finished, abort block seal") - return - case <-time.After(time.Duration(processBackOffTime) * time.Second): - log.Info("[parlia] Process backoff time exhausted, start to seal block") - } - } - - select { - case results <- block.WithSeal(header): - default: - log.Warn("[parlia] Sealing result is not read by miner", "sealhash", SealHash(header, p.chainConfig.ChainID)) - } - }() - - return nil -} - -// SealHash returns the hash of a block prior to it being sealed. -func (p *Parlia) SealHash(header *types.Header) libcommon.Hash { - return SealHash(header, p.chainConfig.ChainID) -} - -// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty -// that a new block should have. -func (p *Parlia) CalcDifficulty(chain consensus.ChainHeaderReader, time, parentTime uint64, parentDifficulty *big.Int, parentNumber uint64, parentHash, parentUncleHash libcommon.Hash, _ uint64) *big.Int { - snap, err := p.snapshot(chain, parentNumber, parentHash, nil, false /* verify */) - if err != nil { - return nil - } - return CalcDifficulty(snap, p.val) -} - -// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty -// that a new block should have based on the previous blocks in the chain and the -// current signer. -func CalcDifficulty(snap *Snapshot, signer libcommon.Address) *big.Int { - if snap.inturn(signer) { - return new(big.Int).Set(diffInTurn) - } - return new(big.Int).Set(diffNoTurn) -} - -func (p *Parlia) GenerateSeal(chain consensus.ChainHeaderReader, current, parent *types.Header, call consensus.Call) []byte { - return nil -} - -// APIs returns the RPC APIs this consensus engine provides. -func (p *Parlia) APIs(chain consensus.ChainHeaderReader) []rpc.API { - return []rpc.API{{ - Namespace: "parlia", - Version: "1.0", - Service: &API{chain: chain, parlia: p}, - Public: false, - }} -} - -func (p *Parlia) IsServiceTransaction(sender libcommon.Address, syscall consensus.SystemCall) bool { - return false -} - -func (p *Parlia) IsSystemTransaction(tx types.Transaction, header *types.Header) (bool, error) { - // deploy a contract - if tx.GetTo() == nil { - return false, nil - } - sender, err := tx.Sender(*p.signer) - if err != nil { - return false, errors.New("UnAuthorized transaction") - } - if sender == header.Coinbase && isToSystemContract(*tx.GetTo()) && tx.GetPrice().IsZero() { - return true, nil - } - return false, nil -} - -func isToSystemContract(to libcommon.Address) bool { - _, ok := systemContracts[to] - return ok -} - -func (p *Parlia) IsSystemContract(to *libcommon.Address) bool { - if to == nil { - return false - } - return isToSystemContract(*to) -} - -func (p *Parlia) shouldWaitForCurrentBlockProcess(chainDb kv.RwDB, header *types.Header, snap *Snapshot) bool { - if header.Difficulty.Cmp(diffInTurn) == 0 { - return false - } - - roTx, err := chainDb.BeginRo(context.Background()) - if err != nil { - return false - } - defer roTx.Rollback() - hash := rawdb.ReadHeadHeaderHash(roTx) - number := rawdb.ReadHeaderNumber(roTx, hash) - - highestVerifiedHeader := rawdb.ReadHeader(roTx, hash, *number) - if highestVerifiedHeader == nil { - return false - } - - if header.ParentHash == highestVerifiedHeader.ParentHash { - return true - } - return false -} - -func (p *Parlia) EnoughDistance(chain consensus.ChainReader, header *types.Header) bool { - snap, err := p.snapshot(chain, header.Number.Uint64()-1, header.ParentHash, nil, false /* verify */) - if err != nil { - return true - } - return snap.enoughDistance(p.val, header) -} - -func (p *Parlia) IsLocalBlock(header *types.Header) bool { - return p.val == header.Coinbase -} - -func (p *Parlia) AllowLightProcess(chain consensus.ChainReader, currentHeader *types.Header) bool { - snap, err := p.snapshot(chain, currentHeader.Number.Uint64()-1, currentHeader.ParentHash, nil, false /* verify */) - if err != nil { - return true - } - - idx := snap.indexOfVal(p.val) - // validator is not allowed to diff sync - return idx < 0 -} - -// Close terminates any background threads maintained by the consensus engine. -func (p *Parlia) Close() error { - return nil -} - -// ========================== interaction with contract/account ========= - -// getCurrentValidators get current validators -func (p *Parlia) getCurrentValidators(header *types.Header, ibs *state.IntraBlockState) ([]libcommon.Address, error) { - // method - var method string - if p.chainConfig.IsEuler(header.Number) { - method = "getMiningValidators" - } else { - method = "getValidators" - } - data, err := p.validatorSetABI.Pack(method) - if err != nil { - log.Error("Unable to pack tx for getValidators", "err", err) - return nil, err - } - // call - msgData := hexutility.Bytes(data) - _, returnData, err := p.systemCall(header.Coinbase, systemcontracts.ValidatorContract, msgData[:], ibs, header, u256.Num0) - if err != nil { - return nil, err - } - var ret0 = new([]libcommon.Address) - out := ret0 - if err := p.validatorSetABI.UnpackIntoInterface(out, method, returnData); err != nil { - return nil, err - } - valz := make([]libcommon.Address, len(*ret0)) - copy(valz, *ret0) - //for i, a := range *ret0 { - // valz[i] = a - //} - return valz, nil -} - -// slash spoiled validators -func (p *Parlia) distributeIncoming(val libcommon.Address, state *state.IntraBlockState, header *types.Header, - txs types.Transactions, receipts types.Receipts, systemTxs types.Transactions, - usedGas *uint64, mining bool, -) (types.Transactions, types.Transactions, types.Receipts, error) { - coinbase := header.Coinbase - balance := state.GetBalance(consensus.SystemAddress).Clone() - if balance.Cmp(u256.Num0) <= 0 { - return txs, systemTxs, receipts, nil - } - state.SetBalance(consensus.SystemAddress, u256.Num0) - state.AddBalance(coinbase, balance) - - doDistributeSysReward := state.GetBalance(systemcontracts.SystemRewardContract).Cmp(maxSystemBalance) < 0 - if doDistributeSysReward { - var rewards = new(uint256.Int) - rewards = rewards.Rsh(balance, systemRewardPercent) - if rewards.Cmp(u256.Num0) > 0 { - var err error - var tx types.Transaction - var receipt *types.Receipt - if systemTxs, tx, receipt, err = p.distributeToSystem(rewards, state, header, len(txs), systemTxs, usedGas, mining); err != nil { - return nil, nil, nil, err - } - txs = append(txs, tx) - receipts = append(receipts, receipt) - //log.Debug("[parlia] distribute to system reward pool", "block hash", header.Hash(), "amount", rewards) - balance = balance.Sub(balance, rewards) - } - } - //log.Debug("[parlia] distribute to validator contract", "block hash", header.Hash(), "amount", balance) - var err error - var tx types.Transaction - var receipt *types.Receipt - if systemTxs, tx, receipt, err = p.distributeToValidator(balance, val, state, header, len(txs), systemTxs, usedGas, mining); err != nil { - return nil, nil, nil, err - } - txs = append(txs, tx) - receipts = append(receipts, receipt) - return txs, systemTxs, receipts, nil -} - -// slash spoiled validators -func (p *Parlia) slash(spoiledVal libcommon.Address, state *state.IntraBlockState, header *types.Header, - txIndex int, systemTxs types.Transactions, usedGas *uint64, mining bool, -) (types.Transactions, types.Transaction, *types.Receipt, error) { - // method - method := "slash" - - // get packed data - data, err := p.slashABI.Pack(method, - spoiledVal, - ) - if err != nil { - log.Error("[parlia] Unable to pack tx for slash", "err", err) - return nil, nil, nil, err - } - // apply message - return p.applyTransaction(header.Coinbase, systemcontracts.SlashContract, u256.Num0, data, state, header, txIndex, systemTxs, usedGas, mining) -} - -// init contract -func (p *Parlia) initContract(state *state.IntraBlockState, header *types.Header, - txs types.Transactions, receipts types.Receipts, systemTxs types.Transactions, - usedGas *uint64, mining bool, -) (types.Transactions, types.Transactions, types.Receipts, error) { - // method - method := "init" - // contracts - contracts := []libcommon.Address{ - systemcontracts.ValidatorContract, - systemcontracts.SlashContract, - systemcontracts.LightClientContract, - systemcontracts.RelayerHubContract, - systemcontracts.TokenHubContract, - systemcontracts.RelayerIncentivizeContract, - systemcontracts.CrossChainContract, - } - // get packed data - data, err := p.validatorSetABI.Pack(method) - if err != nil { - log.Error("[parlia] Unable to pack tx for init validator set", "err", err) - return nil, nil, nil, err - } - for _, c := range contracts { - log.Info("[parlia] init contract", "block hash", header.Hash(), "contract", c) - var tx types.Transaction - var receipt *types.Receipt - if systemTxs, tx, receipt, err = p.applyTransaction(header.Coinbase, c, u256.Num0, data, state, header, len(txs), systemTxs, usedGas, mining); err != nil { - return nil, nil, nil, err - } - txs = append(txs, tx) - receipts = append(receipts, receipt) - } - return txs, systemTxs, receipts, nil -} - -func (p *Parlia) distributeToSystem(amount *uint256.Int, state *state.IntraBlockState, header *types.Header, - txIndex int, systemTxs types.Transactions, - usedGas *uint64, mining bool, -) (types.Transactions, types.Transaction, *types.Receipt, error) { - return p.applyTransaction(header.Coinbase, systemcontracts.SystemRewardContract, amount, nil, state, header, - txIndex, systemTxs, usedGas, mining) -} - -// slash spoiled validators -func (p *Parlia) distributeToValidator(amount *uint256.Int, validator libcommon.Address, state *state.IntraBlockState, header *types.Header, - txIndex int, systemTxs types.Transactions, - usedGas *uint64, mining bool, -) (types.Transactions, types.Transaction, *types.Receipt, error) { - // method - method := "deposit" - - // get packed data - data, err := p.validatorSetABI.Pack(method, - validator, - ) - if err != nil { - log.Error("[parlia] Unable to pack tx for deposit", "err", err) - return nil, nil, nil, err - } - // apply message - return p.applyTransaction(header.Coinbase, systemcontracts.ValidatorContract, amount, data, state, header, txIndex, systemTxs, usedGas, mining) -} - -func (p *Parlia) applyTransaction(from libcommon.Address, to libcommon.Address, value *uint256.Int, data []byte, ibs *state.IntraBlockState, header *types.Header, - txIndex int, systemTxs types.Transactions, usedGas *uint64, mining bool, -) (types.Transactions, types.Transaction, *types.Receipt, error) { - nonce := ibs.GetNonce(from) - expectedTx := types.Transaction(types.NewTransaction(nonce, to, value, math.MaxUint64/2, u256.Num0, data)) - expectedHash := expectedTx.SigningHash(p.chainConfig.ChainID) - if from == p.val && mining { - signature, err := p.signFn(from, expectedTx.SigningHash(p.chainConfig.ChainID).Bytes(), p.chainConfig.ChainID) - if err != nil { - return nil, nil, nil, err - } - signer := types.LatestSignerForChainID(p.chainConfig.ChainID) - expectedTx, err = expectedTx.WithSignature(*signer, signature) - if err != nil { - return nil, nil, nil, err - } - } else { - if len(systemTxs) == 0 { - return nil, nil, nil, fmt.Errorf("supposed to get a actual transaction, but get none") - } - if systemTxs[0] == nil { - return nil, nil, nil, fmt.Errorf("supposed to get a actual transaction, but get nil") - } - actualTx := systemTxs[0] - actualHash := actualTx.SigningHash(p.chainConfig.ChainID) - if !bytes.Equal(actualHash.Bytes(), expectedHash.Bytes()) { - return nil, nil, nil, fmt.Errorf("expected system tx (hash %v, nonce %d, to %s, value %s, gas %d, gasPrice %s, data %s), actual tx (hash %v, nonce %d, to %s, value %s, gas %d, gasPrice %s, data %s)", - expectedHash.String(), - expectedTx.GetNonce(), - expectedTx.GetTo().String(), - expectedTx.GetValue().String(), - expectedTx.GetGas(), - expectedTx.GetPrice().String(), - hex.EncodeToString(expectedTx.GetData()), - actualHash.String(), - actualTx.GetNonce(), - actualTx.GetTo().String(), - actualTx.GetValue().String(), - actualTx.GetGas(), - actualTx.GetPrice().String(), - hex.EncodeToString(actualTx.GetData()), - ) - } - expectedTx = actualTx - // move to next - systemTxs = systemTxs[1:] - } - ibs.Prepare(expectedTx.Hash(), libcommon.Hash{}, txIndex) - gasUsed, _, err := p.systemCall(from, to, data, ibs, header, value) - if err != nil { - return nil, nil, nil, err - } - *usedGas += gasUsed - receipt := types.NewReceipt(false, *usedGas) - receipt.TxHash = expectedTx.Hash() - receipt.GasUsed = gasUsed - if err := ibs.FinalizeTx(p.chainConfig.Rules(header.Number.Uint64(), header.Time), state.NewNoopWriter()); err != nil { - return nil, nil, nil, err - } - // Set the receipt logs and create a bloom for filtering - receipt.Logs = ibs.GetLogs(expectedTx.Hash()) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = header.Hash() - receipt.BlockNumber = header.Number - receipt.TransactionIndex = uint(txIndex) - ibs.SetNonce(from, nonce+1) - return systemTxs, expectedTx, receipt, nil -} - -func (p *Parlia) systemCall(from, contract libcommon.Address, data []byte, ibs *state.IntraBlockState, header *types.Header, value *uint256.Int) (gasUsed uint64, returnData []byte, err error) { - chainConfig := p.chainConfig - if chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(header.Number) == 0 { - misc.ApplyDAOHardFork(ibs) - } - msg := types.NewMessage( - from, - &contract, - 0, value, - math.MaxUint64/2, u256.Num0, - nil, nil, - data, nil, false, - true, // isFree - ) - vmConfig := vm.Config{NoReceipts: true} - // Create a new context to be used in the EVM environment - blockContext := core.NewEVMBlockContext(header, core.GetHashFn(header, nil), p, &from, nil /*excessDataGas*/) - evm := vm.NewEVM(blockContext, core.NewEVMTxContext(msg), ibs, chainConfig, vmConfig) - ret, leftOverGas, err := evm.Call( - vm.AccountRef(msg.From()), - *msg.To(), - msg.Data(), - msg.Gas(), - msg.Value(), - false, - ) - if err != nil { - return 0, nil, err - } - return msg.Gas() - leftOverGas, ret, nil -} diff --git a/consensus/parlia/ramanujanfork.go b/consensus/parlia/ramanujanfork.go deleted file mode 100644 index fbc77b9e4..000000000 --- a/consensus/parlia/ramanujanfork.go +++ /dev/null @@ -1,45 +0,0 @@ -package parlia - -import ( - "fmt" - "math/rand" - "time" - - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/core/types" -) - -const ( - wiggleTimeBeforeFork = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers - fixedBackOffTimeBeforeFork = 200 * time.Millisecond -) - -func (p *Parlia) delayForRamanujanFork(snap *Snapshot, header *types.Header) time.Duration { - delay := time.Until(time.Unix(int64(header.Time), 0)) // nolint: gosimple - if p.chainConfig.IsRamanujan(header.Number.Uint64()) { - return delay - } - if header.Difficulty.Cmp(diffNoTurn) == 0 { - // It's not our turn explicitly to sign, delay it a bit - wiggle := time.Duration(len(snap.Validators)/2+1) * wiggleTimeBeforeFork - delay += fixedBackOffTimeBeforeFork + time.Duration(rand.Int63n(int64(wiggle))) // nolint - } - return delay -} - -func (p *Parlia) blockTimeForRamanujanFork(snap *Snapshot, header, parent *types.Header) uint64 { - blockTime := parent.Time + p.config.Period - if p.chainConfig.IsRamanujan(header.Number.Uint64()) { - blockTime = blockTime + backOffTime(snap, p.val) - } - return blockTime -} - -func (p *Parlia) blockTimeVerifyForRamanujanFork(snap *Snapshot, header, parent *types.Header) error { - if p.chainConfig.IsRamanujan(header.Number.Uint64()) { - if header.Time < parent.Time+p.config.Period+backOffTime(snap, header.Coinbase) { - return fmt.Errorf("header %d, time %d, now %d, period: %d, backof: %d, %w", header.Number.Uint64(), header.Time, time.Now().Unix(), p.config.Period, backOffTime(snap, header.Coinbase), consensus.ErrFutureBlock) - } - } - return nil -} diff --git a/consensus/parlia/snapshot.go b/consensus/parlia/snapshot.go deleted file mode 100644 index 1c3c70076..000000000 --- a/consensus/parlia/snapshot.go +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package parlia - -import ( - "bytes" - "context" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "math/big" - "sort" - - "github.com/hashicorp/golang-lru/v2" - "github.com/ledgerwatch/erigon-lib/chain" - "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon-lib/common/hexutility" - "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/log/v3" - - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/core/types" -) - -// Snapshot is the state of the validatorSet at a given point. -type Snapshot struct { - config *chain.ParliaConfig // Consensus engine parameters to fine tune behavior - sigCache *lru.ARCCache[common.Hash, common.Address] // Cache of recent block signatures to speed up ecrecover - - Number uint64 `json:"number"` // Block number where the snapshot was created - Hash common.Hash `json:"hash"` // Block hash where the snapshot was created - Validators map[common.Address]struct{} `json:"validators"` // Set of authorized validators at this moment - Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections - RecentForkHashes map[uint64]string `json:"recent_fork_hashes"` // Set of recent forkHash -} - -// newSnapshot creates a new snapshot with the specified startup parameters. This -// method does not initialize the set of recent validators, so only ever use it for -// the genesis block. -func newSnapshot( - config *chain.ParliaConfig, - sigCache *lru.ARCCache[common.Hash, common.Address], - number uint64, - hash common.Hash, - validators []common.Address, -) *Snapshot { - snap := &Snapshot{ - config: config, - sigCache: sigCache, - Number: number, - Hash: hash, - Recents: make(map[uint64]common.Address), - RecentForkHashes: make(map[uint64]string), - Validators: make(map[common.Address]struct{}), - } - for _, v := range validators { - snap.Validators[v] = struct{}{} - } - return snap -} - -// validatorsAscending implements the sort interface to allow sorting a list of addresses -type validatorsAscending []common.Address - -func (s validatorsAscending) Len() int { return len(s) } -func (s validatorsAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 } -func (s validatorsAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// SnapshotFullKey = SnapshotBucket + num (uint64 big endian) + hash -func SnapshotFullKey(number uint64, hash common.Hash) []byte { - return append(hexutility.EncodeTs(number), hash.Bytes()...) -} - -var ErrNoSnapsnot = fmt.Errorf("no parlia snapshot") - -// loadSnapshot loads an existing snapshot from the database. -func loadSnapshot(config *chain.ParliaConfig, sigCache *lru.ARCCache[common.Hash, common.Address], db kv.RwDB, num uint64, hash common.Hash) (*Snapshot, error) { - tx, err := db.BeginRo(context.Background()) - if err != nil { - return nil, err - } - defer tx.Rollback() - blob, err := tx.GetOne(kv.ParliaSnapshot, SnapshotFullKey(num, hash)) - if err != nil { - return nil, err - } - - if len(blob) == 0 { - return nil, ErrNoSnapsnot - } - snap := new(Snapshot) - if err := json.Unmarshal(blob, snap); err != nil { - return nil, err - } - snap.config = config - snap.sigCache = sigCache - return snap, nil -} - -// store inserts the snapshot into the database. -func (s *Snapshot) store(db kv.RwDB) error { - blob, err := json.Marshal(s) - if err != nil { - return err - } - return db.UpdateNosync(context.Background(), func(tx kv.RwTx) error { - return tx.Put(kv.ParliaSnapshot, SnapshotFullKey(s.Number, s.Hash), blob) - }) -} - -// copy creates a deep copy of the snapshot -func (s *Snapshot) copy() *Snapshot { - cpy := &Snapshot{ - config: s.config, - sigCache: s.sigCache, - Number: s.Number, - Hash: s.Hash, - Validators: make(map[common.Address]struct{}), - Recents: make(map[uint64]common.Address), - RecentForkHashes: make(map[uint64]string), - } - - for v := range s.Validators { - cpy.Validators[v] = struct{}{} - } - for block, v := range s.Recents { - cpy.Recents[block] = v - } - for block, id := range s.RecentForkHashes { - cpy.RecentForkHashes[block] = id - } - return cpy -} - -// nolint -func (s *Snapshot) isMajorityFork(forkHash string) bool { - ally := 0 - for _, h := range s.RecentForkHashes { - if h == forkHash { - ally++ - } - } - return ally > len(s.RecentForkHashes)/2 -} - -func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderReader, parents []*types.Header, chainId *big.Int, doLog bool) (*Snapshot, error) { - // Allow passing in no headers for cleaner code - if len(headers) == 0 { - return s, nil - } - // Sanity check that the headers can be applied - for i := 0; i < len(headers)-1; i++ { - if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 { - return nil, errOutOfRangeChain - } - if !bytes.Equal(headers[i+1].ParentHash.Bytes(), headers[i].Hash().Bytes()) { - return nil, errBlockHashInconsistent - } - } - if headers[0].Number.Uint64() != s.Number+1 { - return nil, errOutOfRangeChain - } - if !bytes.Equal(headers[0].ParentHash.Bytes(), s.Hash.Bytes()) { - return nil, errBlockHashInconsistent - } - // Iterate through the headers and create a new snapshot - snap := s.copy() - - for _, header := range headers { - number := header.Number.Uint64() - if doLog && number%100_000 == 0 { - log.Info("[parlia] snapshots build, recover from headers", "block", number) - } - // Delete the oldest validator from the recent list to allow it signing again - if limit := uint64(len(snap.Validators)/2 + 1); number >= limit { - delete(snap.Recents, number-limit) - } - if limit := uint64(len(snap.Validators)); number >= limit { - delete(snap.RecentForkHashes, number-limit) - } - // Resolve the authorization key and check against signers - validator, err := ecrecover(header, s.sigCache, chainId) - if err != nil { - return nil, err - } - // Disabling this validation due to issues with BEP-131 looks like is breaks the property that used to allow Erigon to sync Parlia without knowning the contract state - // Further investigation is required - /* - if _, ok := snap.Validators[validator]; !ok { - return nil, errUnauthorizedValidator - } - */ - for _, recent := range snap.Recents { - if recent == validator { - return nil, errRecentlySigned - } - } - snap.Recents[number] = validator - // change validator set - if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) { - checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents) - if checkpointHeader == nil { - return nil, consensus.ErrUnknownAncestor - } - - validatorBytes := checkpointHeader.Extra[extraVanity : len(checkpointHeader.Extra)-extraSeal] - // get validators from headers and use that for new validator set - newValArr, err := ParseValidators(validatorBytes) - if err != nil { - return nil, err - } - newVals := make(map[common.Address]struct{}, len(newValArr)) - for _, val := range newValArr { - newVals[val] = struct{}{} - } - oldLimit := len(snap.Validators)/2 + 1 - newLimit := len(newVals)/2 + 1 - if newLimit < oldLimit { - for i := 0; i < oldLimit-newLimit; i++ { - delete(snap.Recents, number-uint64(newLimit)-uint64(i)) - } - } - oldLimit = len(snap.Validators) - newLimit = len(newVals) - if newLimit < oldLimit { - for i := 0; i < oldLimit-newLimit; i++ { - delete(snap.RecentForkHashes, number-uint64(newLimit)-uint64(i)) - } - } - snap.Validators = newVals - } - snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity]) - } - snap.Number += uint64(len(headers)) - snap.Hash = headers[len(headers)-1].Hash() - return snap, nil -} - -// validators retrieves the list of validators in ascending order. -func (s *Snapshot) validators() []common.Address { - validators := make([]common.Address, 0, len(s.Validators)) - for v := range s.Validators { - validators = append(validators, v) - } - sort.Sort(validatorsAscending(validators)) - return validators -} - -// inturn returns if a validator at a given block height is in-turn or not. -func (s *Snapshot) inturn(validator common.Address) bool { - validators := s.validators() - offset := (s.Number + 1) % uint64(len(validators)) - return validators[offset] == validator -} - -func (s *Snapshot) enoughDistance(validator common.Address, header *types.Header) bool { - idx := s.indexOfVal(validator) - if idx < 0 { - return true - } - validatorNum := int64(len(s.validators())) - if validatorNum == 1 { - return true - } - if validator == header.Coinbase { - return false - } - offset := (int64(s.Number) + 1) % validatorNum - if int64(idx) >= offset { - return int64(idx)-offset >= validatorNum-2 - } else { - return validatorNum+int64(idx)-offset >= validatorNum-2 - } -} - -func (s *Snapshot) indexOfVal(validator common.Address) int { - validators := s.validators() - for idx, val := range validators { - if val == validator { - return idx - } - } - return -1 -} - -func (s *Snapshot) supposeValidator() common.Address { - validators := s.validators() - index := (s.Number + 1) % uint64(len(validators)) - return validators[index] -} - -func ParseValidators(validatorsBytes []byte) ([]common.Address, error) { - if len(validatorsBytes)%validatorBytesLength != 0 { - return nil, errors.New("invalid validators bytes") - } - n := len(validatorsBytes) / validatorBytesLength - result := make([]common.Address, n) - for i := 0; i < n; i++ { - address := make([]byte, validatorBytesLength) - copy(address, validatorsBytes[i*validatorBytesLength:(i+1)*validatorBytesLength]) - result[i] = common.BytesToAddress(address) - } - return result, nil -} - -func FindAncientHeader(header *types.Header, ite uint64, chain consensus.ChainHeaderReader, candidateParents []*types.Header) *types.Header { - ancient := header - for i := uint64(1); i <= ite; i++ { - parentHash := ancient.ParentHash - parentHeight := ancient.Number.Uint64() - 1 - found := false - if len(candidateParents) > 0 { - index := sort.Search(len(candidateParents), func(i int) bool { - return candidateParents[i].Number.Uint64() >= parentHeight - }) - if index < len(candidateParents) && candidateParents[index].Number.Uint64() == parentHeight && - candidateParents[index].Hash() == parentHash { - ancient = candidateParents[index] - found = true - } - } - if !found { - ancient = chain.GetHeader(parentHash, parentHeight) - found = true - } - if ancient == nil || !found { - return nil - } - } - return ancient -} diff --git a/consensus/parlia/snapshot_test.go b/consensus/parlia/snapshot_test.go deleted file mode 100644 index 160408d6f..000000000 --- a/consensus/parlia/snapshot_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package parlia - -import ( - "bytes" - "math/rand" - "sort" - "testing" - - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/stretchr/testify/assert" -) - -func TestValidatorSetSort(t *testing.T) { - size := 100 - validators := make([]libcommon.Address, size) - for i := 0; i < size; i++ { - validators[i] = randomAddress() - } - sort.Sort(validatorsAscending(validators)) - for i := 0; i < size-1; i++ { - assert.True(t, bytes.Compare(validators[i][:], validators[i+1][:]) < 0) - } -} - -func randomAddress() libcommon.Address { - addrBytes := make([]byte, 20) - rand.Read(addrBytes) - return libcommon.BytesToAddress(addrBytes) -} diff --git a/consensus/parlia/utils.go b/consensus/parlia/utils.go deleted file mode 100644 index 6740131d0..000000000 --- a/consensus/parlia/utils.go +++ /dev/null @@ -1,31 +0,0 @@ -package parlia - -import ( - "math/rand" - - libcommon "github.com/ledgerwatch/erigon-lib/common" -) - -func backOffTime(snap *Snapshot, val libcommon.Address) uint64 { - if snap.inturn(val) { - return 0 - } else { - idx := snap.indexOfVal(val) - if idx < 0 { - // The backOffTime does not matter when a validator is not authorized. - return 0 - } - s := rand.NewSource(int64(snap.Number)) - r := rand.New(s) // nolint: gosec - n := len(snap.Validators) - backOffSteps := make([]uint64, 0, n) - for idx := uint64(0); idx < uint64(n); idx++ { - backOffSteps = append(backOffSteps, idx) - } - r.Shuffle(n, func(i, j int) { - backOffSteps[i], backOffSteps[j] = backOffSteps[j], backOffSteps[i] - }) - delay := initialBackOffTime + backOffSteps[idx]*wiggleTime - return delay - } -} diff --git a/core/blockchain.go b/core/blockchain.go index 11006f7c4..b6174c9c0 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -22,16 +22,12 @@ import ( "math/big" "time" - "github.com/ledgerwatch/erigon-lib/chain" - libcommon "github.com/ledgerwatch/erigon-lib/common" + metrics2 "github.com/VictoriaMetrics/metrics" "golang.org/x/crypto/sha3" "golang.org/x/exp/slices" - "github.com/ledgerwatch/erigon/core/systemcontracts" - "github.com/ledgerwatch/erigon/core/vm/evmtypes" - "github.com/ledgerwatch/erigon/rlp" - - metrics2 "github.com/VictoriaMetrics/metrics" + "github.com/ledgerwatch/erigon-lib/chain" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/common/math" "github.com/ledgerwatch/erigon/common/u256" @@ -40,6 +36,8 @@ import ( "github.com/ledgerwatch/erigon/core/state" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/core/vm" + "github.com/ledgerwatch/erigon/core/vm/evmtypes" + "github.com/ledgerwatch/erigon/rlp" ) var ( @@ -72,154 +70,6 @@ type EphemeralExecResult struct { StateSyncReceipt *types.Receipt `json:"-"` } -func ExecuteBlockEphemerallyForBSC( - chainConfig *chain.Config, - vmConfig *vm.Config, - blockHashFunc func(n uint64) libcommon.Hash, - engine consensus.Engine, block *types.Block, - stateReader state.StateReader, stateWriter state.WriterWithChangeSets, - chainReader consensus.ChainHeaderReader, getTracer func(txIndex int, txHash libcommon.Hash) (vm.EVMLogger, error), -) (*EphemeralExecResult, error) { - defer BlockExecutionTimer.UpdateDuration(time.Now()) - block.Uncles() - ibs := state.New(stateReader) - header := block.Header() - usedGas := new(uint64) - gp := new(GasPool) - gp.AddGas(block.GasLimit()) - - var ( - rejectedTxs []*RejectedTx - includedTxs types.Transactions - receipts types.Receipts - ) - - var excessDataGas *big.Int - ph := chainReader.GetHeaderByHash(block.ParentHash()) - if ph != nil { - excessDataGas = ph.ExcessDataGas - } - if !vmConfig.ReadOnly { - if err := InitializeBlockExecution(engine, chainReader, block.Header(), block.Transactions(), block.Uncles(), chainConfig, ibs, nil); err != nil { - return nil, err - } - } - - if chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(block.Number()) == 0 { - misc.ApplyDAOHardFork(ibs) - } - systemcontracts.UpgradeBuildInSystemContract(chainConfig, header.Number, ibs) - noop := state.NewNoopWriter() - posa, isPoSA := engine.(consensus.PoSA) - //fmt.Printf("====txs processing start: %d====\n", block.NumberU64()) - for i, tx := range block.Transactions() { - if isPoSA { - if isSystemTx, err := posa.IsSystemTransaction(tx, block.Header()); err != nil { - return nil, err - } else if isSystemTx { - continue - } - } - ibs.Prepare(tx.Hash(), block.Hash(), i) - writeTrace := false - if vmConfig.Debug && vmConfig.Tracer == nil { - tracer, err := getTracer(i, tx.Hash()) - if err != nil { - return nil, fmt.Errorf("could not obtain tracer: %w", err) - } - vmConfig.Tracer = tracer - writeTrace = true - } - - receipt, _, err := ApplyTransaction(chainConfig, blockHashFunc, engine, nil, gp, ibs, noop, header, tx, usedGas, *vmConfig, excessDataGas) - if writeTrace { - if ftracer, ok := vmConfig.Tracer.(vm.FlushableTracer); ok { - ftracer.Flush(tx) - } - - vmConfig.Tracer = nil - } - if err != nil { - if !vmConfig.StatelessExec { - return nil, fmt.Errorf("could not apply tx %d from block %d [%v]: %w", i, block.NumberU64(), tx.Hash().Hex(), err) - } - rejectedTxs = append(rejectedTxs, &RejectedTx{i, err.Error()}) - } else { - includedTxs = append(includedTxs, tx) - if !vmConfig.NoReceipts { - receipts = append(receipts, receipt) - } - } - } - - var newBlock *types.Block - var receiptSha libcommon.Hash - if !vmConfig.ReadOnly { - // We're doing this hack for BSC to avoid changing consensus interfaces a lot. BSC modifies txs and receipts by appending - // system transactions, and they increase used gas and write cumulative gas to system receipts, that's why we need - // to deduct system gas before. This line is equal to "blockGas-systemGas", but since we don't know how much gas is - // used by system transactions we just override. Of course, we write used by block gas back. It also always true - // that used gas by block is always equal to original's block header gas, and it's checked by receipts root verification - // otherwise it causes block verification error. - header.GasUsed = *usedGas - syscall := func(contract libcommon.Address, data []byte) ([]byte, error) { - return SysCallContract(contract, data, *chainConfig, ibs, header, engine, false /* constCall */, excessDataGas) - } - outTxs, outReceipts, err := engine.Finalize(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, block.Withdrawals(), chainReader, syscall) - if err != nil { - return nil, err - } - *usedGas = header.GasUsed - - // We need repack this block because transactions and receipts might be changed by consensus, and - // it won't pass receipts hash or bloom verification - newBlock = types.NewBlock(block.Header(), outTxs, block.Uncles(), outReceipts, block.Withdrawals()) - // Update receipts - if !vmConfig.NoReceipts { - receipts = outReceipts - } - receiptSha = newBlock.ReceiptHash() - } else { - newBlock = block - receiptSha = types.DeriveSha(receipts) - } - - if chainConfig.IsByzantium(header.Number.Uint64()) && !vmConfig.NoReceipts { - if !vmConfig.StatelessExec && receiptSha != block.ReceiptHash() { - return nil, fmt.Errorf("mismatched receipt headers for block %d (%s != %s)", block.NumberU64(), receiptSha.Hex(), block.ReceiptHash().Hex()) - } - } - if !vmConfig.StatelessExec && newBlock.GasUsed() != header.GasUsed { - return nil, fmt.Errorf("gas used by execution: %d, in header: %d, in new Block: %v", *usedGas, header.GasUsed, newBlock.GasUsed()) - } - - var bloom types.Bloom - if !vmConfig.NoReceipts { - bloom = newBlock.Bloom() - if !vmConfig.StatelessExec && bloom != header.Bloom { - return nil, fmt.Errorf("bloom computed by execution: %x, in header: %x", bloom, header.Bloom) - } - } - - if err := ibs.CommitBlock(chainConfig.Rules(header.Number.Uint64(), header.Time), stateWriter); err != nil { - return nil, fmt.Errorf("committing block %d failed: %w", header.Number.Uint64(), err) - } else if err := stateWriter.WriteChangeSets(); err != nil { - return nil, fmt.Errorf("writing changesets for block %d failed: %w", header.Number.Uint64(), err) - } - - execRs := &EphemeralExecResult{ - TxRoot: types.DeriveSha(includedTxs), - ReceiptRoot: receiptSha, - Bloom: bloom, - Receipts: receipts, - Difficulty: (*math.HexOrDecimal256)(block.Header().Difficulty), - GasUsed: math.HexOrDecimal64(*usedGas), - Rejected: rejectedTxs, - } - - return execRs, nil -} - // ExecuteBlockEphemerally runs a block from provided stateReader and // writes the result to the provided stateWriter func ExecuteBlockEphemerally( diff --git a/core/state_transition.go b/core/state_transition.go index 30c78260d..965ac8486 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/holiman/uint256" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/txpool" types2 "github.com/ledgerwatch/erigon-lib/types" @@ -27,8 +28,6 @@ import ( "github.com/ledgerwatch/erigon/common" cmath "github.com/ledgerwatch/erigon/common/math" "github.com/ledgerwatch/erigon/common/u256" - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/core/vm" "github.com/ledgerwatch/erigon/core/vm/evmtypes" "github.com/ledgerwatch/erigon/crypto" @@ -73,8 +72,7 @@ type StateTransition struct { sharedBuyGas *uint256.Int sharedBuyGasBalance *uint256.Int - isParlia bool - isBor bool + isBor bool } // Message represents a message sent to a contract. @@ -151,7 +149,6 @@ func IntrinsicGas(data []byte, accessList types2.AccessList, isContractCreation // NewStateTransition initialises and returns a new state transition object. func NewStateTransition(evm vm.VMInterface, msg Message, gp *GasPool) *StateTransition { - isParlia := evm.ChainConfig().Parlia != nil isBor := evm.ChainConfig().Bor != nil return &StateTransition{ gp: gp, @@ -167,8 +164,7 @@ func NewStateTransition(evm vm.VMInterface, msg Message, gp *GasPool) *StateTran sharedBuyGas: uint256.NewInt(0), sharedBuyGasBalance: uint256.NewInt(0), - isParlia: isParlia, - isBor: isBor, + isBor: isBor, } } @@ -316,12 +312,6 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*Executi // 5. there is no overflow when calculating intrinsic gas // 6. caller has enough balance to cover asset transfer for **topmost** call - // BSC always gave gas bailout due to system transactions that set 2^256/2 gas limit and - // for Parlia consensus this flag should be always be set - if st.isParlia { - gasBailout = true - } - // Check clauses 1-3 and 6, buy gas if everything is correct if err := st.preCheck(gasBailout); err != nil { return nil, err @@ -340,17 +330,6 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*Executi vmConfig := st.evm.Config() isEIP3860 := vmConfig.HasEip3860(rules) - if rules.IsNano { - for _, blackListAddr := range types.NanoBlackList { - if blackListAddr == sender.Address() { - return nil, fmt.Errorf("block blacklist account") - } - if msg.To() != nil && *msg.To() == blackListAddr { - return nil, fmt.Errorf("block blacklist account") - } - } - } - // Check clauses 4-5, subtract intrinsic gas if everything is correct gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, rules.IsHomestead, rules.IsIstanbul, isEIP3860) if err != nil { @@ -417,11 +396,7 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*Executi } amount := new(uint256.Int).SetUint64(st.gasUsed()) amount.Mul(amount, effectiveTip) // gasUsed * effectiveTip = how much goes to the block producer (miner, validator) - if st.isParlia { - st.state.AddBalance(consensus.SystemAddress, amount) - } else { - st.state.AddBalance(st.evm.Context().Coinbase, amount) - } + st.state.AddBalance(st.evm.Context().Coinbase, amount) if !msg.IsFree() && rules.IsLondon && rules.IsEip1559FeeCollector { burntContractAddress := *st.evm.ChainConfig().Eip1559FeeCollector burnAmount := new(uint256.Int).Mul(new(uint256.Int).SetUint64(st.gasUsed()), st.evm.Context().BaseFee) diff --git a/core/types/accounts/account.go b/core/types/accounts/account.go index e5f65e20f..2512f48c3 100644 --- a/core/types/accounts/account.go +++ b/core/types/accounts/account.go @@ -29,7 +29,6 @@ const ( MimetypeDataWithValidator = "data/validator" MimetypeTypedData = "data/typed" MimetypeClique = "application/x-clique-header" - MimetypeParlia = "application/x-parlia-header" MimetypeBor = "application/x-bor-header" MimetypeTextPlain = "text/plain" ) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index c3a4beb23..1d8c86ec0 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -82,51 +82,6 @@ var PrecompiledContractsIstanbul = map[libcommon.Address]PrecompiledContract{ libcommon.BytesToAddress([]byte{9}): &blake2F{}, } -var PrecompiledContractsIstanbulForBSC = map[libcommon.Address]PrecompiledContract{ - libcommon.BytesToAddress([]byte{1}): &ecrecover{}, - libcommon.BytesToAddress([]byte{2}): &sha256hash{}, - libcommon.BytesToAddress([]byte{3}): &ripemd160hash{}, - libcommon.BytesToAddress([]byte{4}): &dataCopy{}, - libcommon.BytesToAddress([]byte{5}): &bigModExp{}, - libcommon.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, - libcommon.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - libcommon.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - libcommon.BytesToAddress([]byte{9}): &blake2F{}, - - libcommon.BytesToAddress([]byte{100}): &tmHeaderValidate{}, - libcommon.BytesToAddress([]byte{101}): &iavlMerkleProofValidate{}, -} - -var PrecompiledContractsNano = map[libcommon.Address]PrecompiledContract{ - libcommon.BytesToAddress([]byte{1}): &ecrecover{}, - libcommon.BytesToAddress([]byte{2}): &sha256hash{}, - libcommon.BytesToAddress([]byte{3}): &ripemd160hash{}, - libcommon.BytesToAddress([]byte{4}): &dataCopy{}, - libcommon.BytesToAddress([]byte{5}): &bigModExp{}, - libcommon.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, - libcommon.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - libcommon.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - libcommon.BytesToAddress([]byte{9}): &blake2F{}, - - libcommon.BytesToAddress([]byte{100}): &tmHeaderValidateNano{}, - libcommon.BytesToAddress([]byte{101}): &iavlMerkleProofValidateNano{}, -} - -var PrecompiledContractsIsMoran = map[libcommon.Address]PrecompiledContract{ - libcommon.BytesToAddress([]byte{1}): &ecrecover{}, - libcommon.BytesToAddress([]byte{2}): &sha256hash{}, - libcommon.BytesToAddress([]byte{3}): &ripemd160hash{}, - libcommon.BytesToAddress([]byte{4}): &dataCopy{}, - libcommon.BytesToAddress([]byte{5}): &bigModExp{}, - libcommon.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, - libcommon.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - libcommon.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - libcommon.BytesToAddress([]byte{9}): &blake2F{}, - - libcommon.BytesToAddress([]byte{100}): &tmHeaderValidate{}, - libcommon.BytesToAddress([]byte{101}): &iavlMerkleProofValidateMoran{}, -} - // PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum // contracts used in the Berlin release. var PrecompiledContractsBerlin = map[libcommon.Address]PrecompiledContract{ @@ -156,13 +111,10 @@ var PrecompiledContractsBLS = map[libcommon.Address]PrecompiledContract{ } var ( - PrecompiledAddressesMoran []libcommon.Address - PrecompiledAddressesNano []libcommon.Address - PrecompiledAddressesBerlin []libcommon.Address - PrecompiledAddressesIstanbul []libcommon.Address - PrecompiledAddressesIstanbulForBSC []libcommon.Address - PrecompiledAddressesByzantium []libcommon.Address - PrecompiledAddressesHomestead []libcommon.Address + PrecompiledAddressesBerlin []libcommon.Address + PrecompiledAddressesIstanbul []libcommon.Address + PrecompiledAddressesByzantium []libcommon.Address + PrecompiledAddressesHomestead []libcommon.Address ) func init() { @@ -175,33 +127,17 @@ func init() { for k := range PrecompiledContractsIstanbul { PrecompiledAddressesIstanbul = append(PrecompiledAddressesIstanbul, k) } - for k := range PrecompiledContractsIstanbulForBSC { - PrecompiledAddressesIstanbulForBSC = append(PrecompiledAddressesIstanbulForBSC, k) - } for k := range PrecompiledContractsBerlin { PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k) } - for k := range PrecompiledContractsNano { - PrecompiledAddressesNano = append(PrecompiledAddressesNano, k) - } - for k := range PrecompiledContractsIsMoran { - PrecompiledAddressesMoran = append(PrecompiledAddressesMoran, k) - } } // ActivePrecompiles returns the precompiles enabled with the current configuration. func ActivePrecompiles(rules *chain.Rules) []libcommon.Address { switch { - case rules.IsMoran: - return PrecompiledAddressesMoran - case rules.IsNano: - return PrecompiledAddressesNano case rules.IsBerlin: return PrecompiledAddressesBerlin case rules.IsIstanbul: - if rules.IsParlia { - return PrecompiledAddressesIstanbulForBSC - } return PrecompiledAddressesIstanbul case rules.IsByzantium: return PrecompiledAddressesByzantium diff --git a/core/vm/contracts_lightclient.go b/core/vm/contracts_lightclient.go deleted file mode 100644 index e6b11d5e7..000000000 --- a/core/vm/contracts_lightclient.go +++ /dev/null @@ -1,242 +0,0 @@ -package vm - -import ( - "encoding/binary" - "fmt" - "github.com/ledgerwatch/erigon/core/vm/lightclient/iavl" - cmn "github.com/tendermint/tendermint/libs/common" - - "github.com/ledgerwatch/erigon/core/vm/lightclient" - "github.com/ledgerwatch/erigon/params" - "github.com/tendermint/tendermint/crypto/merkle" -) - -const ( - uint64TypeLength uint64 = 8 - precompileContractInputMetaDataLength uint64 = 32 - consensusStateLengthBytesLength uint64 = 32 - - tmHeaderValidateResultMetaDataLength uint64 = 32 - merkleProofValidateResultLength uint64 = 32 -) - -// input: -// consensus state length | consensus state | tendermint header | -// 32 bytes | | | -func decodeTendermintHeaderValidationInput(input []byte) (*lightclient.ConsensusState, *lightclient.Header, error) { - csLen := binary.BigEndian.Uint64(input[consensusStateLengthBytesLength-uint64TypeLength : consensusStateLengthBytesLength]) - if uint64(len(input)) <= consensusStateLengthBytesLength+csLen { - return nil, nil, fmt.Errorf("expected payload size %d, actual size: %d", consensusStateLengthBytesLength+csLen, len(input)) - } - - cs, err := lightclient.DecodeConsensusState(input[consensusStateLengthBytesLength : consensusStateLengthBytesLength+csLen]) - if err != nil { - return nil, nil, err - } - header, err := lightclient.DecodeHeader(input[consensusStateLengthBytesLength+csLen:]) - if err != nil { - return nil, nil, err - } - - return &cs, header, nil -} - -// tmHeaderValidate implemented as a native contract. -type tmHeaderValidate struct{} - -func (c *tmHeaderValidate) RequiredGas(input []byte) uint64 { - return params.TendermintHeaderValidateGas -} - -func (c *tmHeaderValidate) Run(input []byte) (result []byte, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("internal error: %v", r) - } - }() - - if uint64(len(input)) <= precompileContractInputMetaDataLength { - return nil, fmt.Errorf("invalid input") - } - - payloadLength := binary.BigEndian.Uint64(input[precompileContractInputMetaDataLength-uint64TypeLength : precompileContractInputMetaDataLength]) - if uint64(len(input)) != payloadLength+precompileContractInputMetaDataLength { - return nil, fmt.Errorf("invalid input: input size should be %d, actual the size is %d", payloadLength+precompileContractInputMetaDataLength, len(input)) - } - - cs, header, err := decodeTendermintHeaderValidationInput(input[precompileContractInputMetaDataLength:]) - if err != nil { - return nil, err - } - - validatorSetChanged, err := cs.ApplyHeader(header) - if err != nil { - return nil, err - } - - consensusStateBytes, err := cs.EncodeConsensusState() - if err != nil { - return nil, err - } - - // result - // | validatorSetChanged | empty | consensusStateBytesLength | new consensusState | - // | 1 byte | 23 bytes | 8 bytes | | - lengthBytes := make([]byte, tmHeaderValidateResultMetaDataLength) - if validatorSetChanged { - copy(lengthBytes[:1], []byte{0x01}) - } - consensusStateBytesLength := uint64(len(consensusStateBytes)) - binary.BigEndian.PutUint64(lengthBytes[tmHeaderValidateResultMetaDataLength-uint64TypeLength:], consensusStateBytesLength) - - result = append(lengthBytes, consensusStateBytes...) - - return result, nil -} - -//------------------------------------------------------------------------------------------------------------------------------------------------ - -// iavlMerkleProofValidate implemented as a native contract. -type iavlMerkleProofValidate struct { - basicIavlMerkleProofValidate -} - -func (c *iavlMerkleProofValidate) RequiredGas(input []byte) uint64 { - return params.IAVLMerkleProofValidateGas -} - -// input: -// | payload length | payload | -// | 32 bytes | | -func (c *iavlMerkleProofValidate) Run(input []byte) (result []byte, err error) { - return c.basicIavlMerkleProofValidate.Run(input) -} - -// tmHeaderValidate implemented as a native contract. -type tmHeaderValidateNano struct{} - -func (c *tmHeaderValidateNano) RequiredGas(input []byte) uint64 { - return params.TendermintHeaderValidateGas -} - -func (c *tmHeaderValidateNano) Run(input []byte) (result []byte, err error) { - return nil, fmt.Errorf("suspend") -} - -type iavlMerkleProofValidateNano struct{} - -func (c *iavlMerkleProofValidateNano) RequiredGas(_ []byte) uint64 { - return params.IAVLMerkleProofValidateGas -} - -func (c *iavlMerkleProofValidateNano) Run(_ []byte) (result []byte, err error) { - return nil, fmt.Errorf("suspend") -} - -// ------------------------------------------------------------------------------------------------------------------------------------------------ -type iavlMerkleProofValidateMoran struct { - basicIavlMerkleProofValidate -} - -func (c *iavlMerkleProofValidateMoran) RequiredGas(_ []byte) uint64 { - return params.IAVLMerkleProofValidateGas -} - -func (c *iavlMerkleProofValidateMoran) Run(input []byte) (result []byte, err error) { - c.basicIavlMerkleProofValidate.verifiers = []merkle.ProofOpVerifier{ - forbiddenAbsenceOpVerifier, - singleValueOpVerifier, - multiStoreOpVerifier, - forbiddenSimpleValueOpVerifier, - } - return c.basicIavlMerkleProofValidate.Run(input) -} - -type basicIavlMerkleProofValidate struct { - verifiers []merkle.ProofOpVerifier -} - -func (c *basicIavlMerkleProofValidate) Run(input []byte) (result []byte, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("internal error: %v", r) - } - }() - - if uint64(len(input)) <= precompileContractInputMetaDataLength { - return nil, fmt.Errorf("invalid input: input should include %d bytes payload length and payload", precompileContractInputMetaDataLength) - } - - payloadLength := binary.BigEndian.Uint64(input[precompileContractInputMetaDataLength-uint64TypeLength : precompileContractInputMetaDataLength]) - if uint64(len(input)) != payloadLength+precompileContractInputMetaDataLength { - return nil, fmt.Errorf("invalid input: input size should be %d, actual the size is %d", payloadLength+precompileContractInputMetaDataLength, len(input)) - } - - kvmp, err := lightclient.DecodeKeyValueMerkleProof(input[precompileContractInputMetaDataLength:]) - if err != nil { - return nil, err - } - - kvmp.SetVerifiers(c.verifiers) - valid := kvmp.Validate() - if !valid { - return nil, fmt.Errorf("invalid merkle proof") - } - - result = make([]byte, merkleProofValidateResultLength) - binary.BigEndian.PutUint64(result[merkleProofValidateResultLength-uint64TypeLength:], 0x01) - return result, nil -} -func forbiddenAbsenceOpVerifier(op merkle.ProofOperator) error { - if op == nil { - return nil - } - if _, ok := op.(iavl.IAVLAbsenceOp); ok { - return cmn.NewError("absence proof suspend") - } - return nil -} - -func forbiddenSimpleValueOpVerifier(op merkle.ProofOperator) error { - if op == nil { - return nil - } - if _, ok := op.(merkle.SimpleValueOp); ok { - return cmn.NewError("simple value proof suspend") - } - return nil -} - -func multiStoreOpVerifier(op merkle.ProofOperator) error { - if op == nil { - return nil - } - if mop, ok := op.(lightclient.MultiStoreProofOp); ok { - storeNames := make(map[string]bool, len(mop.Proof.StoreInfos)) - for _, store := range mop.Proof.StoreInfos { - if exist := storeNames[store.Name]; exist { - return cmn.NewError("duplicated store") - } else { - storeNames[store.Name] = true - } - } - } - return nil -} - -func singleValueOpVerifier(op merkle.ProofOperator) error { - if op == nil { - return nil - } - if valueOp, ok := op.(iavl.IAVLValueOp); ok { - if len(valueOp.Proof.Leaves) != 1 { - return cmn.NewError("range proof suspended") - } - for _, innerNode := range valueOp.Proof.LeftPath { - if len(innerNode.Right) > 0 && len(innerNode.Left) > 0 { - return cmn.NewError("both right and left hash exit!") - } - } - } - return nil -} diff --git a/core/vm/contracts_lightclient_test.go b/core/vm/contracts_lightclient_test.go deleted file mode 100644 index ef5857904..000000000 --- a/core/vm/contracts_lightclient_test.go +++ /dev/null @@ -1,197 +0,0 @@ -package vm - -import ( - "encoding/binary" - "encoding/hex" - "github.com/stretchr/testify/assert" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/ledgerwatch/erigon/core/vm/lightclient" -) - -const ( - testHeight uint64 = 66848226 -) - -func TestTmHeaderValidateAndMerkleProofValidate(t *testing.T) { - consensusStateBytes, err := hex.DecodeString("42696e616e63652d436861696e2d4e696c650000000000000000000000000000000000000" + - "3fc05e2b7029751d2a6581efc2f79712ec44d8b4981850325a7feadaa58ef4ddaa18a9380d9ab0fc10d18ca0e0832d5f4c063c5489ec1443dfb738" + - "252d038a82131b27ae17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f000000174876e800184e7b103d34c41003f9b" + - "864d5f8c1adda9bd0436b253bb3c844bc739c1e77c9000000174876e8004d420aea843e92a0cfe69d89696dff6827769f9cb52a249af537ce89bf2" + - "a4b74000000174876e800bd03de9f8ab29e2800094e153fac6f696cfa512536c9c2f804dcb2c2c4e4aed6000000174876e8008f4a74a07351895dd" + - "f373057b98fae6dfaf2cd21f37a063e19601078fe470d53000000174876e8004a5d4753eb79f92e80efe22df7aca4f666a4f44bf81c536c4a09d4b" + - "9c5b654b5000000174876e800c80e9abef7ff439c10c68fe8f1303deddfc527718c3b37d8ba6807446e3c827a000000174876e8009142afcc691b7" + - "cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc000000174876e80049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb7" + - "87a5b314a298e000000174876e80004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b6000000174876e8004034b37ce" + - "da8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e8000000174876e800") - require.NoError(t, err) - - cs, err := lightclient.DecodeConsensusState(consensusStateBytes) - require.NoError(t, err) - - headerBytes, err := hex.DecodeString("e3210a92130abb020a02080a121242696e616e63652d436861696e2d4e696c6518e38bf01f220c08e191aef20510f5f4e4c70230dae0c7173a480a20102b54820dd8fb5bc2c4e875ee573fa294d9b7b7ceb362aa8fd21b33dee41b1c12240801122082f341511f3e6b89d6177fd31f8a106013ba09d6e12ef40a7dec885d81b687634220b1b77e6977e0cd0177e3102a78833c9e152aa646ed4fb5a77e8af58c9867eec0522080d9ab0fc10d18ca0e0832d5f4c063c5489ec1443dfb738252d038a82131b27a5a2080d9ab0fc10d18ca0e0832d5f4c063c5489ec1443dfb738252d038a82131b27a6220294d8fbd0b94b767a7eba9840f299a3586da7fe6b5dead3b7eecba193c400f936a20a3e248bc209955054d880e4d89ff3c0419c0cd77681f4b4c6649ead5545054b982011462633d9db7ed78e951f79913fdc8231aa77ec12b12d1100a480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be212b601080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510cebfe23e321406fd60078eb4c2356137dd50036597db267cf61642409276f20ad4b152f91c344bd63ac691bad66e04e228a8b58dca293ff0bd10f8aef6dfbcecae49e32b09d89e10b771a6c01628628596a95e126b04763560c66c0f12b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510a4caa532321418e69cc672973992bb5f76d049a5b2c5ddf77436380142409ed2b74fa835296d552e68c439dd4ee3fa94fb197282edcc1cc815c863ca42a2c9a73475ff6be9064371a61655a3c31d2f0acc89c3a4489ad4c2671aef52360512b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510a69eca2f3214344c39bb8f4512d6cab1f6aafac1811ef9d8afdf38024240de2768ead90011bcbb1914abc1572749ab7b81382eb81cff3b41c56edc12470a7b8a4d61f8b4ca7b2cb7e24706edd219455796b4db74cd36965859f91dc8910312b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510dcdd833b321437ef19af29679b368d2b9e9de3f8769b357866763803424072ddfe0aeb13616b3f17eb60b19a923ec51fcc726625094aa069255c829c8cdd9e242080a1e559b0030fe9a0db19fd34e392bd78df12a9caff9f2b811bc1ac0a12b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510e9f2f859321462633d9db7ed78e951f79913fdc8231aa77ec12b38044240f5f61c640ab2402b44936de0d24e7b439df78bc3ef15467ecb29b92ece4aa0550790d5ce80761f2ac4b0e3283969725c42343749d9b44b179b2d4fced66c5d0412b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510ff90f55532147b343e041ca130000a8bc00c35152bd7e774003738054240df6e298b3efd42eb536e68a0210bc921e8b5dc145fe965f63f4d3490064f239f2a54a6db16c96086e4ae52280c04ad8b32b44f5ff3d41f0c364949ccb628c50312b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510cad7c931321491844d296bd8e591448efc65fd6ad51a888d58fa3806424030298627da1afd28229aac150f553724b594989e59136d6a175d84e45a4dee344ff9e0eeb69fdf29abb6d833adc3e1ccdc87b2a65019ef5fb627c44d9d132c0012b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510c8c296323214b3727172ce6473bc780298a2d66c12f1a14f5b2a38074240918491100730b4523f0c85409f6d1cca9ebc4b8ca6df8d55fe3d85158fa43286608693c50332953e1d3b93e3e78b24e158d6a2275ce8c6c7c07a7a646a19200312b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef2051086f1a2403214b6f20c7faa2b2f6f24518fa02b71cb5f4a09fba338084240ca59c9fc7f6ab660e9970fc03e5ed588ccb8be43fe5a3e8450287b726f29d039e53fe888438f178ac63c3d2ca969cd8c2fbc8606f067634339b6a94a7382960212b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef2051080efbb543214e0dd72609cc106210d1aa13936cb67b93a0aee2138094240e787a21f5cb7052624160759a9d379dd9db144f2b498bca026375c9ce8ecdc2a0936af1c309b3a0f686c92bf5578b595a4ca99036a19c9fc50d3718fd454b30012b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510ddf8d85a3214fc3108dc3814888f4187452182bc1baf83b71bc9380a4240d51ea31f6449eed71de22339722af1edbb0b21401037d85882b32a2ed8ae9127f2df4d1da2092729e582812856227ed6cdf98a3f60203d1ff80bd635fb03bb0912a4070a4f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff010a4b0a1418e69cc672973992bb5f76d049a5b2c5ddf7743612251624de6420184e7b103d34c41003f9b864d5f8c1adda9bd0436b253bb3c844bc739c1e77c91880d0dbc3f4022080d0dbc3f4020a4b0a14344c39bb8f4512d6cab1f6aafac1811ef9d8afdf12251624de64204d420aea843e92a0cfe69d89696dff6827769f9cb52a249af537ce89bf2a4b741880d0dbc3f4022080d0dbc3f4020a4b0a1437ef19af29679b368d2b9e9de3f8769b3578667612251624de6420bd03de9f8ab29e2800094e153fac6f696cfa512536c9c2f804dcb2c2c4e4aed61880d0dbc3f4022080d0dbc3f4020a4b0a1462633d9db7ed78e951f79913fdc8231aa77ec12b12251624de64208f4a74a07351895ddf373057b98fae6dfaf2cd21f37a063e19601078fe470d531880d0dbc3f4022080d0dbc3f4020a4b0a147b343e041ca130000a8bc00c35152bd7e774003712251624de64204a5d4753eb79f92e80efe22df7aca4f666a4f44bf81c536c4a09d4b9c5b654b51880d0dbc3f4022080d0dbc3f4020a4b0a1491844d296bd8e591448efc65fd6ad51a888d58fa12251624de6420c80e9abef7ff439c10c68fe8f1303deddfc527718c3b37d8ba6807446e3c827a1880d0dbc3f4022080d0dbc3f4020a4b0a14b3727172ce6473bc780298a2d66c12f1a14f5b2a12251624de64209142afcc691b7cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc1880d0dbc3f4022080d0dbc3f4020a4b0a14b6f20c7faa2b2f6f24518fa02b71cb5f4a09fba312251624de642049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb787a5b314a298e1880d0dbc3f4022080d0dbc3f4020a4b0a14e0dd72609cc106210d1aa13936cb67b93a0aee2112251624de642004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b61880d0dbc3f4022080d0dbc3f4020a4b0a14fc3108dc3814888f4187452182bc1baf83b71bc912251624de64204034b37ceda8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e81880d0dbc3f4022080d0dbc3f402124f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff011aa4070a4f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff010a4b0a1418e69cc672973992bb5f76d049a5b2c5ddf7743612251624de6420184e7b103d34c41003f9b864d5f8c1adda9bd0436b253bb3c844bc739c1e77c91880d0dbc3f4022080d0dbc3f4020a4b0a14344c39bb8f4512d6cab1f6aafac1811ef9d8afdf12251624de64204d420aea843e92a0cfe69d89696dff6827769f9cb52a249af537ce89bf2a4b741880d0dbc3f4022080d0dbc3f4020a4b0a1437ef19af29679b368d2b9e9de3f8769b3578667612251624de6420bd03de9f8ab29e2800094e153fac6f696cfa512536c9c2f804dcb2c2c4e4aed61880d0dbc3f4022080d0dbc3f4020a4b0a1462633d9db7ed78e951f79913fdc8231aa77ec12b12251624de64208f4a74a07351895ddf373057b98fae6dfaf2cd21f37a063e19601078fe470d531880d0dbc3f4022080d0dbc3f4020a4b0a147b343e041ca130000a8bc00c35152bd7e774003712251624de64204a5d4753eb79f92e80efe22df7aca4f666a4f44bf81c536c4a09d4b9c5b654b51880d0dbc3f4022080d0dbc3f4020a4b0a1491844d296bd8e591448efc65fd6ad51a888d58fa12251624de6420c80e9abef7ff439c10c68fe8f1303deddfc527718c3b37d8ba6807446e3c827a1880d0dbc3f4022080d0dbc3f4020a4b0a14b3727172ce6473bc780298a2d66c12f1a14f5b2a12251624de64209142afcc691b7cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc1880d0dbc3f4022080d0dbc3f4020a4b0a14b6f20c7faa2b2f6f24518fa02b71cb5f4a09fba312251624de642049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb787a5b314a298e1880d0dbc3f4022080d0dbc3f4020a4b0a14e0dd72609cc106210d1aa13936cb67b93a0aee2112251624de642004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b61880d0dbc3f4022080d0dbc3f4020a4b0a14fc3108dc3814888f4187452182bc1baf83b71bc912251624de64204034b37ceda8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e81880d0dbc3f4022080d0dbc3f402124f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff01") - require.NoError(t, err) - - parameterInput := make([]byte, 32+len(consensusStateBytes)+len(headerBytes)) - binary.BigEndian.PutUint64(parameterInput[24:32], uint64(len(consensusStateBytes))) - copy(parameterInput[32:32+len(consensusStateBytes)], consensusStateBytes) - copy(parameterInput[32+len(consensusStateBytes):], headerBytes) - - totalLengthPrefix := make([]byte, 32) - binary.BigEndian.PutUint64(totalLengthPrefix[0:8], 0) - binary.BigEndian.PutUint64(totalLengthPrefix[8:16], 0) - binary.BigEndian.PutUint64(totalLengthPrefix[16:24], 0) - binary.BigEndian.PutUint64(totalLengthPrefix[24:], uint64(len(parameterInput))) - input := append(totalLengthPrefix, parameterInput...) - - var tmHeaderValidateContract tmHeaderValidate - syncedConsensusStateBytes, err := tmHeaderValidateContract.Run(input) - require.NoError(t, err) - syncedConsensusState, err := lightclient.DecodeConsensusState(syncedConsensusStateBytes[32:]) - require.NoError(t, err) - require.Equal(t, testHeight+1, syncedConsensusState.Height) - require.Equal(t, cs.ChainID, syncedConsensusState.ChainID) - - headerBytes, err = hex.DecodeString("c11d0af00e0aba020a02080a121242696e616e63652d436861696e2d4e696c65188596a822220b08bd85c2f30510e8f3d65730a986f7173a480a209e4b742cb3d59618c5af9d9b9d8b6a8408802131a968c6d1e3a516c9548cedc01224080112201dd8f3e89b01db52d79f89a87c8abfe9836e8b828ed33d78e202664dfead9c0e422018c8c46d7665a5db717331ff3deebe8f9986352d308c5950cf1a09286439dd9d522080d9ab0fc10d18ca0e0832d5f4c063c5489ec1443dfb738252d038a82131b27a5a2080d9ab0fc10d18ca0e0832d5f4c063c5489ec1443dfb738252d038a82131b27a6220294d8fbd0b94b767a7eba9840f299a3586da7fe6b5dead3b7eecba193c400f936a202c69c314b4de5c8035253c8bc0771d9ca17b1b23a57c0c6d068b57579791cae2820114b3727172ce6473bc780298a2d66c12f1a14f5b2a12b00c0a480a20c24c5e913fe4b8eec95d473d671c2dfc2cf651118b37e83661a24a1b8ef842251224080112206310a09cbcf41fd71c55e524c7a91f71414bb31ecf6e7b74161e8ec04a3c7b2b120012b9010802108596a82222480a20c24c5e913fe4b8eec95d473d671c2dfc2cf651118b37e83661a24a1b8ef842251224080112206310a09cbcf41fd71c55e524c7a91f71414bb31ecf6e7b74161e8ec04a3c7b2b2a0c08bd85c2f30510cff5c5a102321418e69cc672973992bb5f76d049a5b2c5ddf7743638014240129b1ac9bcf178022f358161f90a0c83d8344be7ad7e1f55c98b4a7f366a95816e80a7e2beac669c73fa5bd6e17693f8a70347ab785c7883a8ef2c9d7464b50a12b9010802108596a82222480a20c24c5e913fe4b8eec95d473d671c2dfc2cf651118b37e83661a24a1b8ef842251224080112206310a09cbcf41fd71c55e524c7a91f71414bb31ecf6e7b74161e8ec04a3c7b2b2a0c08bd85c2f30510e3f7919d023214344c39bb8f4512d6cab1f6aafac1811ef9d8afdf38024240ad6d56ffd8062b70f6c2bf7345a26fcb0a5de2bc477d21e71d780c7f029098aba7efaa2aae1b945602c22d0d1ccdec1e45e7d14d177677a2ba23feeffa88c103120012b9010802108596a82222480a20c24c5e913fe4b8eec95d473d671c2dfc2cf651118b37e83661a24a1b8ef842251224080112206310a09cbcf41fd71c55e524c7a91f71414bb31ecf6e7b74161e8ec04a3c7b2b2a0c08bd85c2f305109c88b58202321462633d9db7ed78e951f79913fdc8231aa77ec12b3804424017c205e1eade76097e659a2c3a20bd7fc61e383b5b631499a8bf26ac81c537d7369ddc5be0c4f8a62c6cfb55d5d6cd4ce75aa57c03888aef365d0702032e6d0c12b9010802108596a82222480a20c24c5e913fe4b8eec95d473d671c2dfc2cf651118b37e83661a24a1b8ef842251224080112206310a09cbcf41fd71c55e524c7a91f71414bb31ecf6e7b74161e8ec04a3c7b2b2a0c08bd85c2f30510bcbda5ff0132147b343e041ca130000a8bc00c35152bd7e7740037380542404c8536a8a2af12e88176699c93ee6c9032240b58b6f92897a7724bd41447f81ae8533e2e3676a44d398296006c1d51d14c9eb2ebca5ac02a5925c549de571b0012b9010802108596a82222480a20c24c5e913fe4b8eec95d473d671c2dfc2cf651118b37e83661a24a1b8ef842251224080112206310a09cbcf41fd71c55e524c7a91f71414bb31ecf6e7b74161e8ec04a3c7b2b2a0c08bd85c2f30510968bff9c02321491844d296bd8e591448efc65fd6ad51a888d58fa38064240f1b55166334e16b2cf1e6bf35521a17b6fc8699807df66495c14508ed5c75b27bf0ba19f7ad4302166d673f027a37148f6ecf4b87fe60b6f196bfc944df3c90412b9010802108596a82222480a20c24c5e913fe4b8eec95d473d671c2dfc2cf651118b37e83661a24a1b8ef842251224080112206310a09cbcf41fd71c55e524c7a91f71414bb31ecf6e7b74161e8ec04a3c7b2b2a0c08bd85c2f30510899ab59f023214b3727172ce6473bc780298a2d66c12f1a14f5b2a38074240b90deb286343c378597d36c381b11f720b9994cc4aefb28ebe840240bd68b4e8855b8508f072133e36a92f4160e5172dd4e086cde6799dc957e3d971784a130e120012b9010802108596a82222480a20c24c5e913fe4b8eec95d473d671c2dfc2cf651118b37e83661a24a1b8ef842251224080112206310a09cbcf41fd71c55e524c7a91f71414bb31ecf6e7b74161e8ec04a3c7b2b2a0c08bd85c2f30510e7c1dffe013214e0dd72609cc106210d1aa13936cb67b93a0aee213809424085424cd5908cc12b9ce35b4891f20af1791f5a7a8f7dfef225a790890a1639badef168a57005ad64d167faf86c97c4bdfeba1d5307182abeb4ef768b4056c00d12b9010802108596a82222480a20c24c5e913fe4b8eec95d473d671c2dfc2cf651118b37e83661a24a1b8ef842251224080112206310a09cbcf41fd71c55e524c7a91f71414bb31ecf6e7b74161e8ec04a3c7b2b2a0c08bd85c2f305108bd8c5ff013214fc3108dc3814888f4187452182bc1baf83b71bc9380a424013382f84fa5d21f6a274159300b5fb20e21705c80b45beff6ca48d84ffa7ab700275e8017bcf69ac70f0c76bd497977c7373e3a9cfdfc09355cf5427272e4d0512a4070a4f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff010a4b0a1418e69cc672973992bb5f76d049a5b2c5ddf7743612251624de6420184e7b103d34c41003f9b864d5f8c1adda9bd0436b253bb3c844bc739c1e77c91880d0dbc3f4022080d0dbc3f4020a4b0a14344c39bb8f4512d6cab1f6aafac1811ef9d8afdf12251624de64204d420aea843e92a0cfe69d89696dff6827769f9cb52a249af537ce89bf2a4b741880d0dbc3f4022080d0dbc3f4020a4b0a1437ef19af29679b368d2b9e9de3f8769b3578667612251624de6420bd03de9f8ab29e2800094e153fac6f696cfa512536c9c2f804dcb2c2c4e4aed61880d0dbc3f4022080d0dbc3f4020a4b0a1462633d9db7ed78e951f79913fdc8231aa77ec12b12251624de64208f4a74a07351895ddf373057b98fae6dfaf2cd21f37a063e19601078fe470d531880d0dbc3f4022080d0dbc3f4020a4b0a147b343e041ca130000a8bc00c35152bd7e774003712251624de64204a5d4753eb79f92e80efe22df7aca4f666a4f44bf81c536c4a09d4b9c5b654b51880d0dbc3f4022080d0dbc3f4020a4b0a1491844d296bd8e591448efc65fd6ad51a888d58fa12251624de6420c80e9abef7ff439c10c68fe8f1303deddfc527718c3b37d8ba6807446e3c827a1880d0dbc3f4022080d0dbc3f4020a4b0a14b3727172ce6473bc780298a2d66c12f1a14f5b2a12251624de64209142afcc691b7cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc1880d0dbc3f4022080d0dbc3f4020a4b0a14b6f20c7faa2b2f6f24518fa02b71cb5f4a09fba312251624de642049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb787a5b314a298e1880d0dbc3f4022080d0dbc3f4020a4b0a14e0dd72609cc106210d1aa13936cb67b93a0aee2112251624de642004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b61880d0dbc3f4022080d0dbc3f4020a4b0a14fc3108dc3814888f4187452182bc1baf83b71bc912251624de64204034b37ceda8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e81880d0dbc3f4022080d0dbc3f402124f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff011aa4070a4f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff010a4b0a1418e69cc672973992bb5f76d049a5b2c5ddf7743612251624de6420184e7b103d34c41003f9b864d5f8c1adda9bd0436b253bb3c844bc739c1e77c91880d0dbc3f4022080d0dbc3f4020a4b0a14344c39bb8f4512d6cab1f6aafac1811ef9d8afdf12251624de64204d420aea843e92a0cfe69d89696dff6827769f9cb52a249af537ce89bf2a4b741880d0dbc3f4022080d0dbc3f4020a4b0a1437ef19af29679b368d2b9e9de3f8769b3578667612251624de6420bd03de9f8ab29e2800094e153fac6f696cfa512536c9c2f804dcb2c2c4e4aed61880d0dbc3f4022080d0dbc3f4020a4b0a1462633d9db7ed78e951f79913fdc8231aa77ec12b12251624de64208f4a74a07351895ddf373057b98fae6dfaf2cd21f37a063e19601078fe470d531880d0dbc3f4022080d0dbc3f4020a4b0a147b343e041ca130000a8bc00c35152bd7e774003712251624de64204a5d4753eb79f92e80efe22df7aca4f666a4f44bf81c536c4a09d4b9c5b654b51880d0dbc3f4022080d0dbc3f4020a4b0a1491844d296bd8e591448efc65fd6ad51a888d58fa12251624de6420c80e9abef7ff439c10c68fe8f1303deddfc527718c3b37d8ba6807446e3c827a1880d0dbc3f4022080d0dbc3f4020a4b0a14b3727172ce6473bc780298a2d66c12f1a14f5b2a12251624de64209142afcc691b7cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc1880d0dbc3f4022080d0dbc3f4020a4b0a14b6f20c7faa2b2f6f24518fa02b71cb5f4a09fba312251624de642049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb787a5b314a298e1880d0dbc3f4022080d0dbc3f4020a4b0a14e0dd72609cc106210d1aa13936cb67b93a0aee2112251624de642004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b61880d0dbc3f4022080d0dbc3f4020a4b0a14fc3108dc3814888f4187452182bc1baf83b71bc912251624de64204034b37ceda8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e81880d0dbc3f4022080d0dbc3f402124f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff01") - require.NoError(t, err) - - syncedConsensusStateBytes = syncedConsensusStateBytes[32:] - parameterInput = make([]byte, 32+len(syncedConsensusStateBytes)+len(headerBytes)) - binary.BigEndian.PutUint64(parameterInput[24:32], uint64(len(syncedConsensusStateBytes))) - copy(parameterInput[32:32+len(syncedConsensusStateBytes)], syncedConsensusStateBytes) - copy(parameterInput[32+len(syncedConsensusStateBytes):], headerBytes) - - totalLengthPrefix = make([]byte, 32) - binary.BigEndian.PutUint64(totalLengthPrefix[24:32], uint64(len(parameterInput))) - input = append(totalLengthPrefix, parameterInput...) - - syncedAgainConsensusStateBytes, err := tmHeaderValidateContract.Run(input) - require.NoError(t, err) - syncedAgainConsensusState, err := lightclient.DecodeConsensusState(syncedAgainConsensusStateBytes[32:]) - require.NoError(t, err) - - newAppHash := syncedAgainConsensusState.AppHash - key, err := hex.DecodeString("6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d") - require.NoError(t, err) - value, err := hex.DecodeString("4bdc4c270a750a148a4e2eb018bdf98a8f53ec755740ffc728637a1d12110a0941544348412d3733301080f69bf321120b0a03424e4210e8baeb8d44120f0a075050432d303041108094ebdc031a26eb5ae98721031c199c92e5b0080967da99be27cf2da53317441b4a663e6d9c6caf02be1fdbdc20d7962b2815") - require.NoError(t, err) - proofBytes, err := hex.DecodeString("0add070a066961766c3a76121c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d1ab407b2070aaf070a2d081810cdfd2b188096a82222209f223f804e2d94ac51c4321b0687397012e6d95eb9783b03bc790da631004c7c0a2d081710adb31a18f395a8222a20d2a38865de82383ccce0140513b65cec1bf2ae6cd7dfeb22eb6faadb4e26b26f0a2d081510b2990b18f395a82222208a02bbd5a695dfc772627ac8744aa9cf30ae26575bdce8c96a9a0d0999175b430a2d081410e6ff0418f395a8222a20d39619c779be909e67f23499fb74eb2c19afd7f21523401d4ccf7e917db5cd600a2d081210e3fe0118f395a8222a20a10cc73843f889d9e03a463eb135e928bb980e19734344cba0fbf4e8a4c5258b0a2c081010dd6518f395a8222a2007fd15843a2fd3f58d021b0e072a6c70742d7a3d993a922445e3491e1c14ee8e0a2c080f10cc2a18eda6a7222a20088942d7b30abd021d8e9505cc41313fad87c8c10a799f3b51018b7b2cfe4ad90a2c080d10b70d18eda6a7222a2091a37bc44d0c61e3752ddc59eb390355ab65e8a9fb453be4f0acec537f1ca14f0a2c080c10890818eda6a72222201cfc317855a06667c45812fe36efe33af05671dfe0d9b56b02662011af2e79e30a2c080b10ac0318c4b0ee212220aeb454a4b3243b6269a2fd8841dca9a951c53b30f1e27da91063dae7224402c70a2c080910e40118c4b0ee212a20441340a4de6498f861b97b3f3ad9603af055e5af51a0d96fff2ae28e3c5c6c9a0a2c0808108d0118c4b0ee212220ae32ea4b9ab7b53571da320e2815fd8b2c278124961cca4a1849a799842424450a2b0807104d18c4b0ee212220e2804c9b7f045ec0b4ab20920a937b82fda8b7a9ddd12b21637335b915cfda550a2b0806102418a5f4c7192a20ec85f22addedfc82c771af5b4c77544b7c1d7c5bbac33f2712dfba1045ebdbd00a2b0805101118a5f4c7192a2071ade34dcc447a0ba8adc603080633d15c06f3525830c86ebce35eca0a4921fc0a2b0804100c18a5f4c7192a205190bce93993e65b266a3417ed511df8897a812cb4b62569e5afcfbec10b69cd0a2b0803100618a5f4c7192220b76c6884f1d412ac10bfb3987fb7d26f0330b2a85539509ebc5c6bdec2f95d520a2b0802100418a5f4c71922206a285b4a4f9d1c687bbafa1f3649b6a6e32b1a85dd0402421210683e846cf0020a2b0801100218a5f4c7192220033b3f7c6dcb258b6e55545e7a4f51539447cd595eb8a2e373ba0015502da1051a450a1c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d12201a272295e94cf1d8090bdb019dde48e9dab026ad2c3e43aaa7e61cc954a9245d18a5f4c7190ab6040a0a6d756c746973746f726512036163631aa204a0040a9d040a300a0364657812290a27088496a822122038fc49f49648fec62acc434151a51eaa378c1b20a730a749548e36f1529422500a300a03676f7612290a27088496a8221220a78ce489bdf08b9ee869c184876e1623dc38b3e64a5cf1a0005f97976c64deac0a380a0b61746f6d69635f7377617012290a27088496a8221220544c2fa38f61e10a39ec00b3e724d5834761268bb455cdbf5843bcf1531f8fbc0a300a0376616c12290a27088496a82212201f71082c9f6f45fb456b2c00b41e50d2f662f2dfec3cb6965f19d214bf02f3980a0f0a046d61696e12070a05088496a8220a320a057374616b6512290a27088496a82212200dd467343c718f240e50b4feac42970fc8c1c69a018be955f9c27913ac1f8b3c0a300a0361636312290a27088496a8221220270c19ccc9c40c5176b3dfbd8af734c97a307e0dbd8df9e286dcd5d709f973ed0a330a06746f6b656e7312290a27088496a8221220c4f96eedf50c83964de9df013afec2e545012d92528b643a5166c828774187b60a320a05706169727312290a27088496a8221220351c55cfda84596ecd22ebc77013662aba97f81f19d9ef3d150213bb07c823060a360a0974696d655f6c6f636b12290a27088496a8221220e7adf5bd30ce022decf0e9341bf05c464ed70cdbc97423bd2bab8f3571e5179b0a330a06706172616d7312290a27088496a822122042a9dfc356ca435db131eb41fb1975c8482f2434537918665e530b0b4633b5f9") - require.NoError(t, err) - - merkleProofInput := make([]byte, 32+32+len(key)+32+len(value)+32+len(proofBytes)) - copy(merkleProofInput[:32], "acc") - binary.BigEndian.PutUint64(merkleProofInput[32+24:32+32], uint64(len(key))) - copy(merkleProofInput[32+32:32+32+len(key)], key) - - binary.BigEndian.PutUint64(merkleProofInput[32+32+len(key)+24:32+32+len(key)+32], uint64(len(value))) - copy(merkleProofInput[32+32+len(key)+32:32+32+len(key)+32+len(value)], value) - - copy(merkleProofInput[32+32+len(key)+32+len(value):32+32+len(key)+32+len(value)+32], newAppHash) - copy(merkleProofInput[32+32+len(key)+32+len(value)+32:], proofBytes) - - totalLengthPrefix = make([]byte, 32) - binary.BigEndian.PutUint64(totalLengthPrefix[0:8], 0) - binary.BigEndian.PutUint64(totalLengthPrefix[8:16], 0) - binary.BigEndian.PutUint64(totalLengthPrefix[16:24], 0) - binary.BigEndian.PutUint64(totalLengthPrefix[24:], uint64(len(merkleProofInput))) - input = append(totalLengthPrefix, merkleProofInput...) - - iavlMerkleProofValidateContract := iavlMerkleProofValidate{} - success, err := iavlMerkleProofValidateContract.Run(input) - require.NoError(t, err) - expectedResult := make([]byte, 32) - binary.BigEndian.PutUint64(expectedResult[24:], 0x01) - require.Equal(t, expectedResult, success) - - moranValidateContract := iavlMerkleProofValidateMoran{} - success, err = moranValidateContract.Run(input) - require.NoError(t, err) - expectedResult = make([]byte, 32) - binary.BigEndian.PutUint64(expectedResult[24:], 0x01) - require.Equal(t, expectedResult, success) -} - -func TestMerkleProofValidateMoran(t *testing.T) { - // Bytest1 is the inputs of exploit tx 0x05356fd06ce56a9ec5b4eaf9c075abd740cae4c21eab1676440ab5cd2fe5c57a - bytest1, _ := hex.DecodeString("00000000000000000000000000000000000000000000000000000000000005086962630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000100380200000000010dd9ac0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000000000f870a0424e4200000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000008ad3c21bcecceda100000094489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec94489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec846553f10072cda827a83531ca0fd7ac917a6b65649719aab0836722caafe0603147a523180a8d020a066961766c3a76120e00000100380200000000010dd9ac1af201f0010aed010a2b0802100318b091c73422200c10f902d266c238a4ca9e26fa9bc36483cd3ebee4e263012f5e7f40c22ee4d20a4d0801100218b091c7342220e4fd47bffd1c06e67edad92b2bf9ca63631978676288a2aa99f95c459436ef632a20121a1f9c4eca726c725796c5375fc4158986ced08e498dc8268ef94d8ed1891612001a370a0e0000010038020000000000000002122011056c6919f02d966991c10721684a8d1542e44003f9ffb47032c18995d4ac7f18b091c7341a340a0e00000100380200000000010dd9ac12202c3a561458f8527b002b5ec3cab2d308662798d6245d4588a4e6a80ebdfe30ac18010ad4050a0a6d756c746973746f726512036962631ac005be050abb050a110a066f7261636c6512070a0508b891c7340a0f0a046d61696e12070a0508b891c7340a350a08736c617368696e6712290a2708b891c7341220c8ccf341e6e695e7e1cb0ce4bf347eea0cc16947d8b4e934ec400b57c59d6f860a380a0b61746f6d69635f7377617012290a2708b891c734122042d4ecc9468f71a70288a95d46564bfcaf2c9f811051dcc5593dbef152976b010a110a0662726964676512070a0508b891c7340a300a0364657812290a2708b891c73412201773be443c27f61075cecdc050ce22eb4990c54679089e90afdc4e0e88182a230a2f0a02736312290a2708b891c7341220df7a0484b7244f76861b1642cfb7a61d923794bd2e076c8dbd05fc4ee29f3a670a330a06746f6b656e7312290a2708b891c734122064958c2f76fec1fa5d1828296e51264c259fa264f499724795a740f48fc4731b0a320a057374616b6512290a2708b891c734122015d2c302143bdf029d58fe381cc3b54cedf77ecb8834dfc5dc3e1555d68f19ab0a330a06706172616d7312290a2708b891c734122050abddcb7c115123a5a4247613ab39e6ba935a3d4f4b9123c4fedfa0895c040a0a300a0361636312290a2708b891c734122079fb5aecc4a9b87e56231103affa5e515a1bdf3d0366490a73e087980b7f1f260a0e0a0376616c12070a0508b891c7340a300a0369626312290a2708b891c7341220e09159530585455058cf1785f411ea44230f39334e6e0f6a3c54dbf069df2b620a300a03676f7612290a2708b891c7341220db85ddd37470983b14186e975a175dfb0bf301b43de685ced0aef18d28b4e0420a320a05706169727312290a2708b891c7341220a78b556bc9e73d86b4c63ceaf146db71b12ac80e4c10dd0ce6eb09c99b0c7cfe0a360a0974696d655f6c6f636b12290a2708b891c73412204775dbe01d41cab018c21ba5c2af94720e4d7119baf693670e70a40ba2a52143") - // Bytest1 is the inputs of exploit tx 0xebf83628ba893d35b496121fb8201666b8e09f3cbadf0e269162baa72efe3b8b - bytest2, _ := hex.DecodeString("00000000000000000000000000000000000000000000000000000000000005086962630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000100380200000000010dd85c0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000000000f870a0424e4200000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000008ad3c21bcecceda100000094489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec94489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec846553f10072cda827a83531ca0fd7ac917a6b65649719aab0836722caafe0603147a523180a8d020a066961766c3a76120e00000100380200000000010dd85c1af201f0010aed010a2b0802100318b091c73422200c10f902d266c238a4ca9e26fa9bc36483cd3ebee4e263012f5e7f40c22ee4d20a4d0801100218b091c7342220e4fd47bffd1c06e67edad92b2bf9ca63631978676288a2aa99f95c459436ef632a20da657c1ffb86c684eb3e265361ef0fa4f9dfa670b45f9f91c5eb6ad84b21a4d112001a370a0e0000010038020000000000000002122011056c6919f02d966991c10721684a8d1542e44003f9ffb47032c18995d4ac7f18b091c7341a340a0e00000100380200000000010dd85c12202c3a561458f8527b002b5ec3cab2d308662798d6245d4588a4e6a80ebdfe30ac18010ad4050a0a6d756c746973746f726512036962631ac005be050abb050a110a066f7261636c6512070a0508b891c7340a0f0a046d61696e12070a0508b891c7340a350a08736c617368696e6712290a2708b891c7341220c8ccf341e6e695e7e1cb0ce4bf347eea0cc16947d8b4e934ec400b57c59d6f860a380a0b61746f6d69635f7377617012290a2708b891c734122042d4ecc9468f71a70288a95d46564bfcaf2c9f811051dcc5593dbef152976b010a110a0662726964676512070a0508b891c7340a300a0364657812290a2708b891c73412201773be443c27f61075cecdc050ce22eb4990c54679089e90afdc4e0e88182a230a2f0a02736312290a2708b891c7341220df7a0484b7244f76861b1642cfb7a61d923794bd2e076c8dbd05fc4ee29f3a670a330a06746f6b656e7312290a2708b891c734122064958c2f76fec1fa5d1828296e51264c259fa264f499724795a740f48fc4731b0a320a057374616b6512290a2708b891c734122015d2c302143bdf029d58fe381cc3b54cedf77ecb8834dfc5dc3e1555d68f19ab0a330a06706172616d7312290a2708b891c734122050abddcb7c115123a5a4247613ab39e6ba935a3d4f4b9123c4fedfa0895c040a0a300a0361636312290a2708b891c734122079fb5aecc4a9b87e56231103affa5e515a1bdf3d0366490a73e087980b7f1f260a0e0a0376616c12070a0508b891c7340a300a0369626312290a2708b891c7341220e09159530585455058cf1785f411ea44230f39334e6e0f6a3c54dbf069df2b620a300a03676f7612290a2708b891c7341220db85ddd37470983b14186e975a175dfb0bf301b43de685ced0aef18d28b4e0420a320a05706169727312290a2708b891c7341220a78b556bc9e73d86b4c63ceaf146db71b12ac80e4c10dd0ce6eb09c99b0c7cfe0a360a0974696d655f6c6f636b12290a2708b891c73412204775dbe01d41cab018c21ba5c2af94720e4d7119baf693670e70a40ba2a52143") - - for _, bytest := range [][]byte{bytest1, bytest2} { - validator := iavlMerkleProofValidate{} - res, err := validator.Run(bytest) - assert.NoError(t, err) - assert.Equal(t, res[len(res)-1], uint8(1)) - - moranValidator := iavlMerkleProofValidateMoran{} - res, err = moranValidator.Run(bytest) - assert.Errorf(t, err, "invalid merkle proof") - assert.Nil(t, res) - } -} - -func TestAbsenceMerkleProofValidateMoran(t *testing.T) { - // Bytest contains absence op - bytest, _ := hex.DecodeString("00000000000000000000000000000000000000000000000000000000000007306163630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d000000000000000000000000000000000000000000000000000000000000007b4bdc4c270a750a148a4e2eb018bdf98a8f53ec755740ffc728637a1d12110a0941544348412d3733301080f69bf321120b0a03424e4210e8baeb8d44120f0a075050432d303041108094ebdc031a26eb5ae98721031c199c92e5b0080967da99be27cf2da53317441b4a663e6d9c6caf02be1fdbdc20d7962b28152c69c314b4de5c8035253c8bc0771d9ca17b1b23a57c0c6d068b57579791cae20add070a066961766c3a61121c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d1ab407b2070aaf070a2d081810cdfd2b188096a82222209f223f804e2d94ac51c4321b0687397012e6d95eb9783b03bc790da631004c7c0a2d081710adb31a18f395a8222a20d2a38865de82383ccce0140513b65cec1bf2ae6cd7dfeb22eb6faadb4e26b26f0a2d081510b2990b18f395a82222208a02bbd5a695dfc772627ac8744aa9cf30ae26575bdce8c96a9a0d0999175b430a2d081410e6ff0418f395a8222a20d39619c779be909e67f23499fb74eb2c19afd7f21523401d4ccf7e917db5cd600a2d081210e3fe0118f395a8222a20a10cc73843f889d9e03a463eb135e928bb980e19734344cba0fbf4e8a4c5258b0a2c081010dd6518f395a8222a2007fd15843a2fd3f58d021b0e072a6c70742d7a3d993a922445e3491e1c14ee8e0a2c080f10cc2a18eda6a7222a20088942d7b30abd021d8e9505cc41313fad87c8c10a799f3b51018b7b2cfe4ad90a2c080d10b70d18eda6a7222a2091a37bc44d0c61e3752ddc59eb390355ab65e8a9fb453be4f0acec537f1ca14f0a2c080c10890818eda6a72222201cfc317855a06667c45812fe36efe33af05671dfe0d9b56b02662011af2e79e30a2c080b10ac0318c4b0ee212220aeb454a4b3243b6269a2fd8841dca9a951c53b30f1e27da91063dae7224402c70a2c080910e40118c4b0ee212a20441340a4de6498f861b97b3f3ad9603af055e5af51a0d96fff2ae28e3c5c6c9a0a2c0808108d0118c4b0ee212220ae32ea4b9ab7b53571da320e2815fd8b2c278124961cca4a1849a799842424450a2b0807104d18c4b0ee212220e2804c9b7f045ec0b4ab20920a937b82fda8b7a9ddd12b21637335b915cfda550a2b0806102418a5f4c7192a20ec85f22addedfc82c771af5b4c77544b7c1d7c5bbac33f2712dfba1045ebdbd00a2b0805101118a5f4c7192a2071ade34dcc447a0ba8adc603080633d15c06f3525830c86ebce35eca0a4921fc0a2b0804100c18a5f4c7192a205190bce93993e65b266a3417ed511df8897a812cb4b62569e5afcfbec10b69cd0a2b0803100618a5f4c7192220b76c6884f1d412ac10bfb3987fb7d26f0330b2a85539509ebc5c6bdec2f95d520a2b0802100418a5f4c71922206a285b4a4f9d1c687bbafa1f3649b6a6e32b1a85dd0402421210683e846cf0020a2b0801100218a5f4c7192220033b3f7c6dcb258b6e55545e7a4f51539447cd595eb8a2e373ba0015502da1051a450a1c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d12201a272295e94cf1d8090bdb019dde48e9dab026ad2c3e43aaa7e61cc954a9245d18a5f4c7190ab6040a0a6d756c746973746f726512036163631aa204a0040a9d040a300a0364657812290a27088496a822122038fc49f49648fec62acc434151a51eaa378c1b20a730a749548e36f1529422500a300a03676f7612290a27088496a8221220a78ce489bdf08b9ee869c184876e1623dc38b3e64a5cf1a0005f97976c64deac0a380a0b61746f6d69635f7377617012290a27088496a8221220544c2fa38f61e10a39ec00b3e724d5834761268bb455cdbf5843bcf1531f8fbc0a300a0376616c12290a27088496a82212201f71082c9f6f45fb456b2c00b41e50d2f662f2dfec3cb6965f19d214bf02f3980a0f0a046d61696e12070a05088496a8220a320a057374616b6512290a27088496a82212200dd467343c718f240e50b4feac42970fc8c1c69a018be955f9c27913ac1f8b3c0a300a0361636312290a27088496a8221220270c19ccc9c40c5176b3dfbd8af734c97a307e0dbd8df9e286dcd5d709f973ed0a330a06746f6b656e7312290a27088496a8221220c4f96eedf50c83964de9df013afec2e545012d92528b643a5166c828774187b60a320a05706169727312290a27088496a8221220351c55cfda84596ecd22ebc77013662aba97f81f19d9ef3d150213bb07c823060a360a0974696d655f6c6f636b12290a27088496a8221220e7adf5bd30ce022decf0e9341bf05c464ed70cdbc97423bd2bab8f3571e5179b0a330a06706172616d7312290a27088496a822122042a9dfc356ca435db131eb41fb1975c8482f2434537918665e530b0b4633b5f9") - moranValidator := iavlMerkleProofValidateMoran{} - res, err := moranValidator.Run(bytest) - assert.Errorf(t, err, "invalid merkle proof") - assert.Nil(t, res) -} - -func TestMultiStore(t *testing.T) { - goodProof := lightclient.NewMultiStoreProofOp([]byte("legit"), &lightclient.MultiStoreProof{ - StoreInfos: []lightclient.StoreInfo{ - { - Name: "legit", - Core: lightclient.StoreCore{ - CommitID: lightclient.CommitID{ - Version: 1, - Hash: []byte("legithash"), - }, - }, - }, - }, - }) - - result1, err := goodProof.Run([][]byte{[]byte("legithash")}) - assert.NoError(t, err) - - _, err = goodProof.Run([][]byte{[]byte("evilhash")}) - assert.Error(t, err, "hash mismatch for substore") - - badProof := lightclient.NewMultiStoreProofOp([]byte("legit"), &lightclient.MultiStoreProof{ - StoreInfos: []lightclient.StoreInfo{ - { - Name: "legit", - Core: lightclient.StoreCore{ - CommitID: lightclient.CommitID{ - Version: 1, - Hash: []byte("evilhash"), - }, - }, - }, - { - Name: "legit", - Core: lightclient.StoreCore{ - CommitID: lightclient.CommitID{ - Version: 1, - Hash: []byte("legithash"), - }, - }, - }, - }, - }) - - _, err = badProof.Run([][]byte{[]byte("legithash")}) - assert.Error(t, err, "hash mismatch for substore") - - result2, err := badProof.Run([][]byte{[]byte("evilhash")}) - assert.NoError(t, err) - assert.Equal(t, result1, result2) - - err = multiStoreOpVerifier(badProof) - assert.Error(t, err, "duplicated store") -} diff --git a/core/vm/evm.go b/core/vm/evm.go index c7ae784ff..632ee1d0d 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -37,18 +37,10 @@ var emptyCodeHash = crypto.Keccak256Hash(nil) func (evm *EVM) precompile(addr libcommon.Address) (PrecompiledContract, bool) { var precompiles map[libcommon.Address]PrecompiledContract switch { - case evm.chainRules.IsMoran: - precompiles = PrecompiledContractsIsMoran - case evm.chainRules.IsNano: - precompiles = PrecompiledContractsNano case evm.chainRules.IsBerlin: precompiles = PrecompiledContractsBerlin case evm.chainRules.IsIstanbul: - if evm.chainRules.IsParlia { - precompiles = PrecompiledContractsIstanbulForBSC - } else { - precompiles = PrecompiledContractsIstanbul - } + precompiles = PrecompiledContractsIstanbul case evm.chainRules.IsByzantium: precompiles = PrecompiledContractsByzantium default: diff --git a/eth/backend.go b/eth/backend.go index 54980719a..d205db455 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -32,6 +32,12 @@ import ( "time" "github.com/holiman/uint256" + "github.com/ledgerwatch/log/v3" + "golang.org/x/exp/slices" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/protobuf/types/known/emptypb" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/datadir" @@ -54,18 +60,6 @@ import ( txpool2 "github.com/ledgerwatch/erigon-lib/txpool" "github.com/ledgerwatch/erigon-lib/txpool/txpooluitl" types2 "github.com/ledgerwatch/erigon-lib/types" - "github.com/ledgerwatch/log/v3" - "golang.org/x/exp/slices" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - "google.golang.org/protobuf/types/known/emptypb" - - "github.com/ledgerwatch/erigon/core/systemcontracts" - "github.com/ledgerwatch/erigon/p2p/enode" - - "github.com/ledgerwatch/erigon/core/state/historyv2read" - "github.com/ledgerwatch/erigon/core/state/temporal" - "github.com/ledgerwatch/erigon/core/types/accounts" "github.com/ledgerwatch/erigon/cl/clparams" clcore "github.com/ledgerwatch/erigon/cmd/erigon-cl/core" @@ -80,11 +74,14 @@ import ( "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/clique" "github.com/ledgerwatch/erigon/consensus/ethash" - "github.com/ledgerwatch/erigon/consensus/parlia" "github.com/ledgerwatch/erigon/consensus/serenity" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" + "github.com/ledgerwatch/erigon/core/state/historyv2read" + "github.com/ledgerwatch/erigon/core/state/temporal" + "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/core/types/accounts" "github.com/ledgerwatch/erigon/core/vm" "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/eth/ethconfig" @@ -98,6 +95,7 @@ import ( "github.com/ledgerwatch/erigon/ethstats" "github.com/ledgerwatch/erigon/node" "github.com/ledgerwatch/erigon/p2p" + "github.com/ledgerwatch/erigon/p2p/enode" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/engineapi" @@ -237,11 +235,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { log.Info("Initialised chain configuration", "config", chainConfig, "genesis", genesis.Hash()) - // Apply special hacks for BSC params - if chainConfig.Parlia != nil { - params.ApplyBinanceSmartChainParams() - } - if err := chainKv.Update(context.Background(), func(tx kv.RwTx) error { if err = stagedsync.UpdateMetrics(tx); err != nil { return err @@ -446,8 +439,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } else if chainConfig.Aura != nil { config.Aura.Etherbase = config.Miner.Etherbase consensusConfig = &config.Aura - } else if chainConfig.Parlia != nil { - consensusConfig = &config.Parlia } else if chainConfig.Bor != nil { consensusConfig = &config.Bor } else { @@ -838,25 +829,6 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy }) } - var prl *parlia.Parlia - if p, ok := s.engine.(*parlia.Parlia); ok { - prl = p - } else if cl, ok := s.engine.(*serenity.Serenity); ok { - if p, ok := cl.InnerEngine().(*parlia.Parlia); ok { - prl = p - } - } - if prl != nil { - if cfg.SigKey == nil { - log.Error("Etherbase account unavailable locally", "err", err) - return fmt.Errorf("signer missing: %w", err) - } - - prl.Authorize(eb, func(validator libcommon.Address, payload []byte, chainId *big.Int) ([]byte, error) { - return crypto.Sign(payload, cfg.SigKey) - }) - } - var borcfg *bor.Bor if b, ok := s.engine.(*bor.Bor); ok { borcfg = b diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 2fb179976..4bbbc670e 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -206,7 +206,6 @@ type Config struct { Clique params.ConsensusSnapshotConfig Aura chain.AuRaConfig - Parlia chain.ParliaConfig Bor chain.BorConfig // Transaction pool options diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 05e2faf4a..ff557ae08 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -35,7 +35,6 @@ func (c Config) MarshalTOML() (interface{}, error) { Ethash ethashcfg.Config Clique params.ConsensusSnapshotConfig Aura chain.AuRaConfig - Parlia chain.ParliaConfig TxPool DeprecatedTxPoolConfig GPO gaspricecfg.Config RPCGasCap uint64 `toml:",omitempty"` @@ -60,7 +59,6 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.Ethash = c.Ethash enc.Clique = c.Clique enc.Aura = c.Aura - enc.Parlia = c.Parlia enc.TxPool = c.DeprecatedTxPool enc.GPO = c.GPO enc.RPCGasCap = c.RPCGasCap @@ -88,7 +86,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { Ethash *ethashcfg.Config Clique *params.ConsensusSnapshotConfig Aura *chain.AuRaConfig - Parlia *chain.ParliaConfig TxPool *DeprecatedTxPoolConfig GPO *gaspricecfg.Config RPCGasCap *uint64 `toml:",omitempty"` @@ -146,9 +143,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.Aura != nil { c.Aura = *dec.Aura } - if dec.Parlia != nil { - c.Parlia = *dec.Parlia - } if dec.TxPool != nil { c.DeprecatedTxPool = *dec.TxPool } diff --git a/eth/ethconsensusconfig/config.go b/eth/ethconsensusconfig/config.go index fe3123a87..02bb9f395 100644 --- a/eth/ethconsensusconfig/config.go +++ b/eth/ethconsensusconfig/config.go @@ -3,13 +3,12 @@ package ethconsensusconfig import ( "path/filepath" - "github.com/ledgerwatch/erigon-lib/chain" - "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/ethash/ethashcfg" - "github.com/davecgh/go-spew/spew" "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/aura" "github.com/ledgerwatch/erigon/consensus/aura/consensusconfig" @@ -21,7 +20,7 @@ import ( "github.com/ledgerwatch/erigon/consensus/clique" "github.com/ledgerwatch/erigon/consensus/db" "github.com/ledgerwatch/erigon/consensus/ethash" - "github.com/ledgerwatch/erigon/consensus/parlia" + "github.com/ledgerwatch/erigon/consensus/ethash/ethashcfg" "github.com/ledgerwatch/erigon/consensus/serenity" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/turbo/snapshotsync" @@ -70,13 +69,6 @@ func CreateConsensusEngine(chainConfig *chain.Config, config interface{}, notify panic(err) } } - case *chain.ParliaConfig: - if chainConfig.Parlia != nil { - if consensusCfg.DBPath == "" { - consensusCfg.DBPath = filepath.Join(datadir, "parlia") - } - eng = parlia.New(chainConfig, db.OpenDatabase(consensusCfg.DBPath, consensusCfg.InMemory, readonly), snapshots, chainDb[0]) - } case *chain.BorConfig: // If Matic bor consensus is requested, set it up // In order to pass the ethereum transaction tests, we need to set the burn contract which is in the bor config diff --git a/eth/stagedsync/exec3.go b/eth/stagedsync/exec3.go index 7a1a1e957..baf0eeacb 100644 --- a/eth/stagedsync/exec3.go +++ b/eth/stagedsync/exec3.go @@ -463,9 +463,6 @@ func ExecV3(ctx context.Context, applyWorker.ResetTx(applyTx) } - _, isPoSa := cfg.engine.(consensus.PoSA) - //isBor := cfg.chainConfig.Bor != nil - slowDownLimit := time.NewTicker(time.Second) defer slowDownLimit.Stop() @@ -480,7 +477,7 @@ Loop: return err } if b == nil { - // TODO: panic here and see that overall prodcess deadlock + // TODO: panic here and see that overall process deadlock return fmt.Errorf("nil block %d", blockNum) } txs := b.Transactions() @@ -580,7 +577,7 @@ Loop: count++ applyWorker.RunTxTask(txTask) if err := func() error { - if txTask.Final && !isPoSa { + if txTask.Final { gasUsed += txTask.UsedGas if gasUsed != txTask.Header.GasUsed { if txTask.BlockNum > 0 { //Disable check for genesis. Maybe need somehow improve it in future - to satisfy TestExecutionSpec diff --git a/eth/stagedsync/stage_execute.go b/eth/stagedsync/stage_execute.go index 2eca369fd..869d49727 100644 --- a/eth/stagedsync/stage_execute.go +++ b/eth/stagedsync/stage_execute.go @@ -165,13 +165,10 @@ func executeBlock( var receipts types.Receipts var stateSyncReceipt *types.Receipt var execRs *core.EphemeralExecResult - _, isPoSa := cfg.engine.(consensus.PoSA) isBor := cfg.chainConfig.Bor != nil getHashFn := core.GetHashFn(block.Header(), getHeader) - if isPoSa { - execRs, err = core.ExecuteBlockEphemerallyForBSC(cfg.chainConfig, &vmConfig, getHashFn, cfg.engine, block, stateReader, stateWriter, ChainReaderImpl{config: cfg.chainConfig, tx: tx, blockReader: cfg.blockReader}, getTracer) - } else if isBor { + if isBor { execRs, err = core.ExecuteBlockEphemerallyBor(cfg.chainConfig, &vmConfig, getHashFn, cfg.engine, block, stateReader, stateWriter, ChainReaderImpl{config: cfg.chainConfig, tx: tx, blockReader: cfg.blockReader}, getTracer) } else { execRs, err = core.ExecuteBlockEphemerally(cfg.chainConfig, &vmConfig, getHashFn, cfg.engine, block, stateReader, stateWriter, ChainReaderImpl{config: cfg.chainConfig, tx: tx, blockReader: cfg.blockReader}, getTracer) diff --git a/eth/stagedsync/stage_headers.go b/eth/stagedsync/stage_headers.go index 2275ec616..a57cb9ccb 100644 --- a/eth/stagedsync/stage_headers.go +++ b/eth/stagedsync/stage_headers.go @@ -118,15 +118,15 @@ func SpawnStageHeaders( preProgress = s.BlockNumber } - notBorAndParlia := cfg.chainConfig.Bor == nil && cfg.chainConfig.Parlia == nil + notBor := cfg.chainConfig.Bor == nil unsettledForkChoice, headHeight := cfg.hd.GetUnsettledForkChoice() - if notBorAndParlia && unsettledForkChoice != nil { // some work left to do after unwind + if notBor && unsettledForkChoice != nil { // some work left to do after unwind return finishHandlingForkChoice(unsettledForkChoice, headHeight, s, tx, cfg, useExternalTx) } transitionedToPoS := cfg.chainConfig.TerminalTotalDifficultyPassed - if notBorAndParlia && !transitionedToPoS { + if notBor && !transitionedToPoS { var err error transitionedToPoS, err = rawdb.Transitioned(tx, preProgress, cfg.chainConfig.TerminalTotalDifficulty) if err != nil { diff --git a/eth/stagedsync/stage_mining_exec.go b/eth/stagedsync/stage_mining_exec.go index 76c001dbd..dadf96783 100644 --- a/eth/stagedsync/stage_mining_exec.go +++ b/eth/stagedsync/stage_mining_exec.go @@ -251,7 +251,7 @@ func getNextTransactions( func filterBadTransactions(transactions []types.Transaction, config chain.Config, blockNumber uint64, baseFee *big.Int, simulationTx *memdb.MemoryMutation) ([]types.Transaction, error) { initialCnt := len(transactions) var filtered []types.Transaction - gasBailout := config.Consensus == chain.ParliaConsensus + gasBailout := false missedTxs := 0 noSenderCnt := 0 diff --git a/eth/stagedsync/stage_snapshots.go b/eth/stagedsync/stage_snapshots.go index 211784480..1ce54740c 100644 --- a/eth/stagedsync/stage_snapshots.go +++ b/eth/stagedsync/stage_snapshots.go @@ -10,6 +10,8 @@ import ( "time" "github.com/holiman/uint256" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/cmp" @@ -22,8 +24,8 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/kvcfg" "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" "github.com/ledgerwatch/erigon-lib/state" + "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/parlia" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/ethconfig/estimate" @@ -31,7 +33,6 @@ import ( "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/erigon/turbo/snapshotsync/snapcfg" - "github.com/ledgerwatch/log/v3" ) type SnapshotsCfg struct { @@ -214,7 +215,6 @@ func FillDBFromSnapshots(logPrefix string, ctx context.Context, tx kv.RwTx, dirs // for now easier just store them in db td := big.NewInt(0) blockNumBytes := make([]byte, 8) - chainReader := &ChainReaderImpl{config: &chainConfig, tx: tx, blockReader: blockReader} if err := snapshotsync.ForEachHeader(ctx, sn, func(header *types.Header) error { blockNum, blockHash := header.Number.Uint64(), header.Hash() td.Add(td, header.Difficulty) @@ -230,20 +230,6 @@ func FillDBFromSnapshots(logPrefix string, ctx context.Context, tx kv.RwTx, dirs return err } - if engine != nil { - // consensus may have own database, let's fill it - // different consensuses may have some conditions for validators snapshots - need := false - switch engine.(type) { - case *parlia.Parlia: - need = (blockNum-1)%(100*parlia.CheckpointInterval) == 0 - } - if need { - if err := engine.VerifyHeader(chainReader, header, true /* seal */); err != nil { - return err - } - } - } select { case <-ctx.Done(): return ctx.Err() diff --git a/go.mod b/go.mod index 551602965..3adeff1d3 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon go 1.19 require ( - github.com/ledgerwatch/erigon-lib v0.0.0-20230413101817-5e9e729d3ce3 + github.com/ledgerwatch/erigon-lib v0.0.0-20230413113449-ace13f88ddad github.com/ledgerwatch/erigon-snapshot v1.1.1-0.20230404044759-5dec854ce336 github.com/ledgerwatch/log/v3 v3.7.0 github.com/ledgerwatch/secp256k1 v1.0.0 diff --git a/go.sum b/go.sum index 6ab9c6d88..b111c0117 100644 --- a/go.sum +++ b/go.sum @@ -527,8 +527,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0= 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-20230413101817-5e9e729d3ce3 h1:oo8E+wE18V2awVlVU8w8uuSGPo9zlyzRYRxZGVw5X3w= -github.com/ledgerwatch/erigon-lib v0.0.0-20230413101817-5e9e729d3ce3/go.mod h1:jfv6zfkuhalm02Q7wzlmjDdDHf9jxRLO/KM/1aJMhlw= +github.com/ledgerwatch/erigon-lib v0.0.0-20230413113449-ace13f88ddad h1:Y9qQM9CVeN9G2GOmBpIGILJenI5ZZ2/7WRRDAkd4hU0= +github.com/ledgerwatch/erigon-lib v0.0.0-20230413113449-ace13f88ddad/go.mod h1:jfv6zfkuhalm02Q7wzlmjDdDHf9jxRLO/KM/1aJMhlw= github.com/ledgerwatch/erigon-snapshot v1.1.1-0.20230404044759-5dec854ce336 h1:Yxmt4Wyd0RCLr7UJJAl0ApCP/f5qkWfvHfgPbnI8ghM= github.com/ledgerwatch/erigon-snapshot v1.1.1-0.20230404044759-5dec854ce336/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= github.com/ledgerwatch/log/v3 v3.7.0 h1:aFPEZdwZx4jzA3+/Pf8wNDN5tCI0cIolq/kfvgcM+og= diff --git a/params/protocol_params.go b/params/protocol_params.go index b34caab01..e4cc0669c 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -18,15 +18,11 @@ package params import "math/big" -// GasLimitBoundDivisor it can be changed by BSC -var ( - GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. -) - const ( - MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be. - MaxGasLimit uint64 = 0x7fffffffffffffff // Maximum the gas limit may ever be. - GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block. + GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. + MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be. + MaxGasLimit uint64 = 0x7fffffffffffffff // Maximum the gas limit may ever be. + GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block. MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero. @@ -189,7 +185,3 @@ var ( MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. ) - -func ApplyBinanceSmartChainParams() { - GasLimitBoundDivisor = 256 -}