mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 03:30:37 +00:00
Add Parlia consensus engine for Binance Smart Chain support (#3086)
* Add Parlia consensus engine for Binance Smart Chain support * Leave RamanujanBlock as nil in params/config.go * Run `go fmt` on files needing it * Add comment for PoSA * Remove empty branches and ineffectual assignments in parlia.go * Remove commented imports * Fix compilation error * Remove EIP155Signer in transaction_signing.go * Fix compilation issue * Fix go fmt issues * Remove Ramanujan from print statement * Remove references to EthAPIBackend approach * Fix Finalize method across consensus engines * Run go fmt * More linting * Remove more changes * remove a comment * Remove unneeded hashing function * Remove bytes check and fix actual vs expected mistake
This commit is contained in:
parent
5413a4db91
commit
ee99f17fbe
@ -3771,7 +3771,7 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit
|
||||
|
||||
if !vmConfig.ReadOnly {
|
||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||
if _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil, nil, nil, nil); err != nil {
|
||||
if _, _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil, nil, nil, nil); err != nil {
|
||||
return nil, fmt.Errorf("finalize of block %d failed: %w", block.NumberU64(), err)
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/ledgerwatch/erigon/cmd/rpcdaemon/interfaces"
|
||||
"github.com/ledgerwatch/erigon/cmd/sentry/download"
|
||||
"github.com/ledgerwatch/erigon/cmd/utils"
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
"github.com/ledgerwatch/erigon/common/dbutils"
|
||||
"github.com/ledgerwatch/erigon/consensus"
|
||||
"github.com/ledgerwatch/erigon/consensus/ethash"
|
||||
@ -1072,12 +1073,15 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig)
|
||||
|
||||
genesis, chainConfig := byChain()
|
||||
var engine consensus.Engine
|
||||
config := ðconfig.Defaults
|
||||
var consensusConfig interface{}
|
||||
if chainConfig.Clique != nil {
|
||||
c := params.CliqueSnapshot
|
||||
c.DBPath = path.Join(datadir, "clique/db")
|
||||
engine = ethconfig.CreateConsensusEngine(chainConfig, logger, c, nil, false)
|
||||
engine = ethconfig.CreateConsensusEngine(chainConfig, logger, c, config.Miner.Notify, config.Miner.Noverify, common.Hash{})
|
||||
} else if chainConfig.Aura != nil {
|
||||
engine = ethconfig.CreateConsensusEngine(chainConfig, logger, ¶ms.AuRaConfig{DBPath: path.Join(datadir, "aura")}, nil, false)
|
||||
consensusConfig = ¶ms.AuRaConfig{DBPath: path.Join(datadir, "aura")}
|
||||
engine = ethconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, common.Hash{})
|
||||
} else { //ethash
|
||||
engine = ethash.NewFaker()
|
||||
}
|
||||
|
@ -695,7 +695,7 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit
|
||||
|
||||
if !vmConfig.ReadOnly {
|
||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||
if _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil, nil, nil, nil); err != nil {
|
||||
if _, _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil, nil, nil, nil); err != nil {
|
||||
return nil, fmt.Errorf("finalize of block %d failed: %w", block.NumberU64(), err)
|
||||
}
|
||||
|
||||
|
@ -22,12 +22,13 @@ import (
|
||||
|
||||
// Common big integers often used
|
||||
var (
|
||||
Num0 = uint256.NewInt(0)
|
||||
Num1 = uint256.NewInt(1)
|
||||
Num2 = uint256.NewInt(2)
|
||||
Num4 = uint256.NewInt(4)
|
||||
Num8 = uint256.NewInt(8)
|
||||
Num27 = uint256.NewInt(27)
|
||||
Num32 = uint256.NewInt(32)
|
||||
Num35 = uint256.NewInt(35)
|
||||
Num0 = uint256.NewInt(0)
|
||||
Num1 = uint256.NewInt(1)
|
||||
Num2 = uint256.NewInt(2)
|
||||
Num4 = uint256.NewInt(4)
|
||||
Num8 = uint256.NewInt(8)
|
||||
Num27 = uint256.NewInt(27)
|
||||
Num32 = uint256.NewInt(32)
|
||||
Num35 = uint256.NewInt(35)
|
||||
Num148 = uint256.NewInt(148)
|
||||
)
|
||||
|
@ -833,11 +833,11 @@ func (c *AuRa) Initialize(config *params.ChainConfig, chain consensus.ChainHeade
|
||||
}
|
||||
|
||||
//word `signal epoch` == word `pending epoch`
|
||||
func (c *AuRa) Finalize(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, r types.Receipts, e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall) error {
|
||||
func (c *AuRa) Finalize(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, r types.Receipts, e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall) (systemTxs []types.Transaction, usedGas uint64, err error) {
|
||||
// accumulateRewards retrieves rewards for a block and applies them to the coinbase accounts for miner and uncle miners
|
||||
beneficiaries, _, rewards, err := AccumulateRewards(config, c, header, uncles, syscall)
|
||||
if err != nil {
|
||||
return fmt.Errorf("buildAncestrySubChain: %w", err)
|
||||
return systemTxs, usedGas, fmt.Errorf("buildAncestrySubChain: %w", err)
|
||||
}
|
||||
for i := range beneficiaries {
|
||||
//fmt.Printf("beneficiary: n=%d, %x,%d\n", header.Number.Uint64(), beneficiaries[i], rewards[i])
|
||||
@ -850,14 +850,14 @@ func (c *AuRa) Finalize(config *params.ChainConfig, header *types.Header, state
|
||||
}
|
||||
pendingTransitionProof, err := c.cfg.Validators.signalEpochEnd(header.Number.Uint64() == 0, header, r)
|
||||
if err != nil {
|
||||
return err
|
||||
return systemTxs, usedGas, err
|
||||
}
|
||||
if pendingTransitionProof != nil {
|
||||
if header.Number.Uint64() >= DEBUG_LOG_FROM {
|
||||
fmt.Printf("insert_pending_trancition: %d,receipts=%d, lenProof=%d\n", header.Number.Uint64(), len(r), len(pendingTransitionProof))
|
||||
}
|
||||
if err = e.PutPendingEpoch(header.Hash(), header.Number.Uint64(), pendingTransitionProof); err != nil {
|
||||
return err
|
||||
return systemTxs, usedGas, err
|
||||
}
|
||||
}
|
||||
// check_and_lock_block -> check_epoch_end_signal END
|
||||
@ -866,17 +866,17 @@ func (c *AuRa) Finalize(config *params.ChainConfig, header *types.Header, state
|
||||
c.EpochManager.finalityChecker.print(header.Number.Uint64())
|
||||
epochEndProof, err := isEpochEnd(chain, e, finalized, header)
|
||||
if err != nil {
|
||||
return err
|
||||
return systemTxs, usedGas, err
|
||||
}
|
||||
if epochEndProof != nil {
|
||||
c.EpochManager.noteNewEpoch()
|
||||
log.Info("[aura] epoch transition", "block_num", header.Number.Uint64())
|
||||
if err := e.PutEpoch(header.Hash(), header.Number.Uint64(), epochEndProof); err != nil {
|
||||
return err
|
||||
return systemTxs, usedGas, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return systemTxs, usedGas, nil
|
||||
}
|
||||
|
||||
func buildFinality(e *EpochManager, chain consensus.ChainHeaderReader, er consensus.EpochReader, validators ValidatorSet, header *types.Header, syscall consensus.SystemCall) []unAssembledHeader {
|
||||
@ -977,11 +977,11 @@ func allHeadersUntil(chain consensus.ChainHeaderReader, from *types.Header, to c
|
||||
|
||||
// FinalizeAndAssemble implements consensus.Engine
|
||||
func (c *AuRa) FinalizeAndAssemble(chainConfig *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, r types.Receipts,
|
||||
e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall, call consensus.Call) (*types.Block, error) {
|
||||
e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall, call consensus.Call) (*types.Block, []*types.Receipt, error) {
|
||||
c.Finalize(chainConfig, header, state, txs, uncles, r, e, chain, syscall)
|
||||
|
||||
// Assemble and return the final block for sealing
|
||||
return types.NewBlock(header, txs, uncles, r), nil
|
||||
return types.NewBlock(header, txs, uncles, r), r, nil
|
||||
}
|
||||
|
||||
// Authorize injects a private key into the consensus engine to mint new blocks
|
||||
|
@ -369,21 +369,22 @@ func (c *Clique) Initialize(config *params.ChainConfig, chain consensus.ChainHea
|
||||
|
||||
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
||||
// rewards given.
|
||||
func (c *Clique) Finalize(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, r types.Receipts, e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall) error {
|
||||
func (c *Clique) Finalize(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, receipts types.Receipts, e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall) (systemTxs []types.Transaction, usedGas uint64, err error) {
|
||||
// No block rewards in PoA, so the state remains as is and uncles are dropped
|
||||
header.UncleHash = types.CalcUncleHash(nil)
|
||||
return nil
|
||||
return systemTxs, usedGas, nil
|
||||
}
|
||||
|
||||
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
|
||||
// nor block rewards given, and returns the final block.
|
||||
func (c *Clique) FinalizeAndAssemble(chainConfig *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, receipts types.Receipts,
|
||||
e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall, call consensus.Call) (*types.Block, error) {
|
||||
e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall, call consensus.Call) (*types.Block, []*types.Receipt, error) {
|
||||
// No block rewards in PoA, so the state remains as is and uncles are dropped
|
||||
// header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) // Covalent todo: Is this needed? We will have to resolve it
|
||||
header.UncleHash = types.CalcUncleHash(nil)
|
||||
|
||||
// Assemble and return the final block for sealing
|
||||
return types.NewBlock(header, txs, nil, receipts), nil
|
||||
return types.NewBlock(header, txs, nil, receipts), receipts, nil
|
||||
}
|
||||
|
||||
// Authorize injects a private key into the consensus engine to mint new blocks
|
||||
|
@ -28,6 +28,10 @@ import (
|
||||
"github.com/ledgerwatch/erigon/rpc"
|
||||
)
|
||||
|
||||
var (
|
||||
SystemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
|
||||
)
|
||||
|
||||
// ChainHeaderReader defines a small collection of methods needed to access the local
|
||||
// blockchain during header verification.
|
||||
type ChainHeaderReader interface {
|
||||
@ -104,7 +108,7 @@ type Engine interface {
|
||||
//
|
||||
// Note: The block header and state database might be updated to reflect any
|
||||
// consensus rules that happen at finalization (e.g. block rewards).
|
||||
Finalize(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, r types.Receipts, e EpochReader, chain ChainHeaderReader, syscall SystemCall) error
|
||||
Finalize(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, r types.Receipts, e EpochReader, chain ChainHeaderReader, syscall SystemCall) (systemTxs []types.Transaction, usedGas uint64, err error)
|
||||
|
||||
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
|
||||
// rewards) and assembles the final block.
|
||||
@ -112,7 +116,7 @@ type Engine interface {
|
||||
// Note: The block header and state database might be updated to reflect any
|
||||
// consensus rules that happen at finalization (e.g. block rewards).
|
||||
FinalizeAndAssemble(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction,
|
||||
uncles []*types.Header, receipts types.Receipts, e EpochReader, chain ChainHeaderReader, syscall SystemCall, call Call) (*types.Block, error)
|
||||
uncles []*types.Header, receipts types.Receipts, e EpochReader, chain ChainHeaderReader, syscall SystemCall, call Call) (*types.Block, []*types.Receipt, error)
|
||||
|
||||
// Seal generates a new sealing request for the given input block and pushes
|
||||
// the result into the given channel.
|
||||
@ -144,3 +148,13 @@ type PoW interface {
|
||||
// Hashrate returns the current mining hashrate of a PoW consensus engine.
|
||||
Hashrate() float64
|
||||
}
|
||||
|
||||
// PoSA is a consensus engine based on proof-of-stake-authority used by Binance Smart Chain.
|
||||
type PoSA interface {
|
||||
Engine
|
||||
|
||||
IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error)
|
||||
IsSystemContract(to *common.Address) bool
|
||||
EnoughDistance(chain ChainReader, header *types.Header) bool
|
||||
IsLocalBlock(header *types.Header) bool
|
||||
}
|
||||
|
@ -608,21 +608,21 @@ func (ethash *Ethash) Initialize(config *params.ChainConfig, chain consensus.Cha
|
||||
|
||||
// Finalize implements consensus.Engine, accumulating the block and uncle rewards,
|
||||
// setting the final state on the header
|
||||
func (ethash *Ethash) Finalize(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, r types.Receipts, e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall) error {
|
||||
func (ethash *Ethash) Finalize(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, receipts types.Receipts, e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall) (systemTxs []types.Transaction, usedGas uint64, err error) {
|
||||
// Accumulate any block and uncle rewards and commit the final state root
|
||||
accumulateRewards(config, state, header, uncles)
|
||||
return nil
|
||||
return nil, usedGas, nil
|
||||
}
|
||||
|
||||
// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
|
||||
// uncle rewards, setting the final state and assembling the block.
|
||||
func (ethash *Ethash) FinalizeAndAssemble(chainConfig *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, r types.Receipts,
|
||||
e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall, call consensus.Call) (*types.Block, error) {
|
||||
e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall, call consensus.Call) (*types.Block, []*types.Receipt, error) {
|
||||
|
||||
// Finalize block
|
||||
ethash.Finalize(chainConfig, header, state, txs, uncles, r, e, chain, syscall)
|
||||
// Header seems complete, assemble into a block and return
|
||||
return types.NewBlock(header, txs, uncles, r), nil
|
||||
return types.NewBlock(header, txs, uncles, r), r, nil
|
||||
}
|
||||
|
||||
// SealHash returns the hash of a block prior to it being sealed.
|
||||
|
676
consensus/parlia/abi.go
Normal file
676
consensus/parlia/abi.go
Normal file
@ -0,0 +1,676 @@
|
||||
package parlia
|
||||
|
||||
const validatorSetABI = `
|
||||
[
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "batchTransfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "validator",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "deprecatedDeposit",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address payable",
|
||||
"name": "validator",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "directTransfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "systemTransfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "validator",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "validatorDeposit",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "validator",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"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": true,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "validatorMisdemeanor",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [],
|
||||
"name": "validatorSetUpdated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "CHANNEL_ID",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint8",
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "DUSTY_INCOMING",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "EXTRA_FEE",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "JAIL_MESSAGE_TYPE",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint8",
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "RELAYER_REWARD",
|
||||
"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": "VALIDATORS_UPDATE_MESSAGE_TYPE",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint8",
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "alreadyInit",
|
||||
"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": [],
|
||||
"name": "fromChainId",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "initLightClientAddr",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "initSlashContract",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "initSystemRewardAddr",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address payable",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "initTokenHubAddr",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "initValidatorSetBytes",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "keyPrefix",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "previousDepositHeight",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "sequence",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "toChainId",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "totalInComing",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "init",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "valAddr",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "deposit",
|
||||
"outputs": [],
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "msgBytes",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "proof",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "height",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "packageSequence",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"name": "update",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getValidators",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address[]",
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"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": "misdemeanor",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "validator",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "felony",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
`
|
88
consensus/parlia/api.go
Normal file
88
consensus/parlia/api.go
Normal file
@ -0,0 +1,88 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package parlia
|
||||
|
||||
import (
|
||||
"github.com/ledgerwatch/erigon/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)
|
||||
}
|
||||
|
||||
// GetSnapshotAtHash retrieves the state snapshot at a given block.
|
||||
func (api *API) GetSnapshotAtHash(hash common.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)
|
||||
}
|
||||
|
||||
// GetValidators retrieves the list of validators at the specified block.
|
||||
func (api *API) GetValidators(number *rpc.BlockNumber) ([]common.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)
|
||||
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 common.Hash) ([]common.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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snap.validators(), nil
|
||||
}
|
31
consensus/parlia/keys.go
Normal file
31
consensus/parlia/keys.go
Normal file
@ -0,0 +1,31 @@
|
||||
package parlia
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
)
|
||||
|
||||
// SnapshotFullKey = SnapshotBucket + num (uint64 big endian) + hash
|
||||
func SnapshotFullKey(number uint64, hash common.Hash) []byte {
|
||||
return append(EncodeBlockNumber(number), hash.Bytes()...)
|
||||
}
|
||||
|
||||
// SnapshotKey = SnapshotBucket + num (uint64 big endian)
|
||||
func SnapshotKey(number uint64) []byte {
|
||||
return EncodeBlockNumber(number)
|
||||
}
|
||||
|
||||
// SnapshotKey = SnapshotBucket + '0'
|
||||
func LastSnapshotKey() []byte {
|
||||
return []byte{0}
|
||||
}
|
||||
|
||||
const NumberLength = 8
|
||||
|
||||
// EncodeBlockNumber encodes a block number as big endian uint64
|
||||
func EncodeBlockNumber(number uint64) []byte {
|
||||
enc := make([]byte, NumberLength)
|
||||
binary.BigEndian.PutUint64(enc, number)
|
||||
return enc
|
||||
}
|
1278
consensus/parlia/parlia.go
Normal file
1278
consensus/parlia/parlia.go
Normal file
File diff suppressed because it is too large
Load Diff
146
consensus/parlia/parlia_test.go
Normal file
146
consensus/parlia/parlia_test.go
Normal file
@ -0,0 +1,146 @@
|
||||
package parlia
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
)
|
||||
|
||||
func TestImpactOfValidatorOutOfService(t *testing.T) {
|
||||
testCases := []struct {
|
||||
totalValidators int
|
||||
downValidators int
|
||||
}{
|
||||
{3, 1},
|
||||
{5, 2},
|
||||
{10, 1},
|
||||
{10, 4},
|
||||
{21, 1},
|
||||
{21, 3},
|
||||
{21, 5},
|
||||
{21, 10},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
simulateValidatorOutOfService(tc.totalValidators, tc.downValidators)
|
||||
}
|
||||
}
|
||||
|
||||
func simulateValidatorOutOfService(totalValidators int, downValidators int) {
|
||||
downBlocks := 10000
|
||||
recoverBlocks := 10000
|
||||
recents := make(map[uint64]int)
|
||||
|
||||
validators := make(map[int]bool, totalValidators)
|
||||
down := make([]int, totalValidators)
|
||||
for i := 0; i < totalValidators; i++ {
|
||||
validators[i] = true
|
||||
down[i] = i
|
||||
}
|
||||
rand.Shuffle(totalValidators, func(i, j int) {
|
||||
down[i], down[j] = down[j], down[i]
|
||||
})
|
||||
for i := 0; i < downValidators; i++ {
|
||||
delete(validators, down[i])
|
||||
}
|
||||
isRecentSign := func(idx int) bool {
|
||||
for _, signIdx := range recents {
|
||||
if signIdx == idx {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
isInService := func(idx int) bool {
|
||||
return validators[idx]
|
||||
}
|
||||
|
||||
downDelay := uint64(0)
|
||||
for h := 1; h <= downBlocks; h++ {
|
||||
if limit := uint64(totalValidators/2 + 1); uint64(h) >= limit {
|
||||
delete(recents, uint64(h)-limit)
|
||||
}
|
||||
proposer := h % totalValidators
|
||||
if !isInService(proposer) || isRecentSign(proposer) {
|
||||
candidates := make(map[int]bool, totalValidators/2)
|
||||
for v := range validators {
|
||||
if !isRecentSign(v) {
|
||||
candidates[v] = true
|
||||
}
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
panic("can not test such case")
|
||||
}
|
||||
idx, delay := producerBlockDelay(candidates, h, totalValidators)
|
||||
downDelay = downDelay + delay
|
||||
recents[uint64(h)] = idx
|
||||
} else {
|
||||
recents[uint64(h)] = proposer
|
||||
}
|
||||
}
|
||||
fmt.Printf("average delay is %v when there is %d validators and %d is down \n",
|
||||
downDelay/uint64(downBlocks), totalValidators, downValidators)
|
||||
|
||||
for i := 0; i < downValidators; i++ {
|
||||
validators[down[i]] = true
|
||||
}
|
||||
|
||||
recoverDelay := uint64(0)
|
||||
lastseen := downBlocks
|
||||
for h := downBlocks + 1; h <= downBlocks+recoverBlocks; h++ {
|
||||
if limit := uint64(totalValidators/2 + 1); uint64(h) >= limit {
|
||||
delete(recents, uint64(h)-limit)
|
||||
}
|
||||
proposer := h % totalValidators
|
||||
if !isInService(proposer) || isRecentSign(proposer) {
|
||||
lastseen = h
|
||||
candidates := make(map[int]bool, totalValidators/2)
|
||||
for v := range validators {
|
||||
if !isRecentSign(v) {
|
||||
candidates[v] = true
|
||||
}
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
panic("can not test such case")
|
||||
}
|
||||
idx, delay := producerBlockDelay(candidates, h, totalValidators)
|
||||
recoverDelay = recoverDelay + delay
|
||||
recents[uint64(h)] = idx
|
||||
} else {
|
||||
recents[uint64(h)] = proposer
|
||||
}
|
||||
}
|
||||
fmt.Printf("total delay is %v after recover when there is %d validators down ever, last seen not proposer at height %d\n",
|
||||
recoverDelay, downValidators, lastseen)
|
||||
}
|
||||
|
||||
func producerBlockDelay(candidates map[int]bool, height, numOfValidators int) (int, uint64) {
|
||||
|
||||
s := rand.NewSource(int64(height))
|
||||
r := rand.New(s)
|
||||
n := numOfValidators
|
||||
backOffSteps := make([]int, 0, n)
|
||||
for idx := 0; idx < n; idx++ {
|
||||
backOffSteps = append(backOffSteps, idx)
|
||||
}
|
||||
r.Shuffle(n, func(i, j int) {
|
||||
backOffSteps[i], backOffSteps[j] = backOffSteps[j], backOffSteps[i]
|
||||
})
|
||||
minDelay := numOfValidators
|
||||
minCandidate := 0
|
||||
for c := range candidates {
|
||||
if minDelay > backOffSteps[c] {
|
||||
minDelay = backOffSteps[c]
|
||||
minCandidate = c
|
||||
}
|
||||
}
|
||||
delay := initialBackOffTime + uint64(minDelay)*wiggleTime
|
||||
return minCandidate, delay
|
||||
}
|
||||
|
||||
func randomAddress() common.Address {
|
||||
addrBytes := make([]byte, 20)
|
||||
rand.Read(addrBytes)
|
||||
return common.BytesToAddress(addrBytes)
|
||||
}
|
44
consensus/parlia/ramanujanfork.go
Normal file
44
consensus/parlia/ramanujanfork.go
Normal file
@ -0,0 +1,44 @@
|
||||
package parlia
|
||||
|
||||
import (
|
||||
"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.IsRamanujanBigInt(header.Number) {
|
||||
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 += time.Duration(fixedBackOffTimeBeforeFork) + time.Duration(rand.Int63n(int64(wiggle)))
|
||||
}
|
||||
return delay
|
||||
}
|
||||
|
||||
func (p *Parlia) blockTimeForRamanujanFork(snap *Snapshot, header, parent *types.Header) uint64 {
|
||||
blockTime := parent.Time + p.config.Period
|
||||
if p.chainConfig.IsRamanujanBigInt(header.Number) {
|
||||
blockTime = blockTime + backOffTime(snap, p.val)
|
||||
}
|
||||
return blockTime
|
||||
}
|
||||
|
||||
func (p *Parlia) blockTimeVerifyForRamanujanFork(snap *Snapshot, header, parent *types.Header) error {
|
||||
if p.chainConfig.IsRamanujanBigInt(header.Number) {
|
||||
if header.Time < parent.Time+p.config.Period+backOffTime(snap, header.Coinbase) {
|
||||
return consensus.ErrFutureBlock
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
329
consensus/parlia/snapshot.go
Normal file
329
consensus/parlia/snapshot.go
Normal file
@ -0,0 +1,329 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package parlia
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"math/big"
|
||||
"sort"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/ledgerwatch/erigon-lib/kv"
|
||||
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
"github.com/ledgerwatch/erigon/consensus"
|
||||
"github.com/ledgerwatch/erigon/core/types"
|
||||
"github.com/ledgerwatch/erigon/params"
|
||||
)
|
||||
|
||||
// Snapshot is the state of the validatorSet at a given point.
|
||||
type Snapshot struct {
|
||||
config *params.ParliaConfig // Consensus engine parameters to fine tune behavior
|
||||
sigCache *lru.ARCCache // 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 *params.ParliaConfig,
|
||||
sigCache *lru.ARCCache,
|
||||
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] }
|
||||
|
||||
const parliaSnapshot = "ParliaSnapshot"
|
||||
|
||||
// // loadSnapshot loads an existing snapshot from the database.
|
||||
func loadSnapshot(config *params.ParliaConfig, sigCache *lru.ARCCache, 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(parliaSnapshot, SnapshotFullKey(num, hash))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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.Update(context.Background(), func(tx kv.RwTx) error {
|
||||
return tx.Put(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
|
||||
}
|
||||
|
||||
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) (*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()
|
||||
// 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
|
||||
}
|
||||
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) % int64(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
|
||||
}
|
23
consensus/parlia/snapshot_test.go
Normal file
23
consensus/parlia/snapshot_test.go
Normal file
@ -0,0 +1,23 @@
|
||||
package parlia
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
)
|
||||
|
||||
func TestValidatorSetSort(t *testing.T) {
|
||||
size := 100
|
||||
validators := make([]common.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)
|
||||
}
|
||||
}
|
@ -167,7 +167,7 @@ func ExecuteBlockEphemerally(
|
||||
}
|
||||
}
|
||||
if !vmConfig.ReadOnly {
|
||||
if err := FinalizeBlockExecution(engine, stateReader, block.Header(), block.Transactions(), block.Uncles(), stateWriter, chainConfig, ibs, receipts, epochReader, chainReader); err != nil {
|
||||
if err := FinalizeBlockExecution(engine, stateReader, block.Header(), block.Transactions(), block.Uncles(), stateWriter, chainConfig, ibs, receipts, usedGas, epochReader, chainReader); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -237,11 +237,11 @@ func CallContractTx(contract common.Address, data []byte, ibs *state.IntraBlockS
|
||||
return tx.FakeSign(from)
|
||||
}
|
||||
|
||||
func FinalizeBlockExecution(engine consensus.Engine, stateReader state.StateReader, header *types.Header, txs types.Transactions, uncles []*types.Header, stateWriter state.WriterWithChangeSets, cc *params.ChainConfig, ibs *state.IntraBlockState, receipts types.Receipts, e consensus.EpochReader, headerReader consensus.ChainHeaderReader) error {
|
||||
func FinalizeBlockExecution(engine consensus.Engine, stateReader state.StateReader, header *types.Header, txs types.Transactions, uncles []*types.Header, stateWriter state.WriterWithChangeSets, cc *params.ChainConfig, ibs *state.IntraBlockState, receipts types.Receipts, usedGas *uint64, e consensus.EpochReader, headerReader consensus.ChainHeaderReader) error {
|
||||
//ibs.Print(cc.Rules(header.Number.Uint64()))
|
||||
//fmt.Printf("====tx processing end====\n")
|
||||
|
||||
if err := engine.Finalize(cc, header, ibs, txs, uncles, receipts, e, headerReader, func(contract common.Address, data []byte) ([]byte, error) {
|
||||
if _, _, err := engine.Finalize(cc, header, ibs, txs, uncles, receipts, e, headerReader, func(contract common.Address, data []byte) ([]byte, error) {
|
||||
return SysCallContract(contract, data, *cc, ibs, header, engine)
|
||||
}); err != nil {
|
||||
return err
|
||||
|
@ -285,7 +285,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||
}
|
||||
if b.engine != nil {
|
||||
// Finalize and seal the block
|
||||
if _, err := b.engine.FinalizeAndAssemble(config, b.header, ibs, b.txs, b.uncles, b.receipts, nil, nil, nil, nil); err != nil {
|
||||
if _, _, err := b.engine.FinalizeAndAssemble(config, b.header, ibs, b.txs, b.uncles, b.receipts, nil, nil, nil, nil); err != nil {
|
||||
return nil, nil, fmt.Errorf("call to FinaliseAndAssemble: %w", err)
|
||||
}
|
||||
// Write state changes to db
|
||||
|
@ -76,6 +76,28 @@ func NewIDFromForks(forks []uint64, genesis common.Hash, head uint64) ID {
|
||||
return ID{Hash: checksumToBytes(hash), Next: next}
|
||||
}
|
||||
|
||||
func NextForkHash(config *params.ChainConfig, genesis common.Hash, head uint64) [4]byte {
|
||||
// Calculate the starting checksum from the genesis hash
|
||||
hash := crc32.ChecksumIEEE(genesis[:])
|
||||
|
||||
// Calculate the current fork checksum and the next fork block
|
||||
var next uint64
|
||||
for _, fork := range GatherForks(config) {
|
||||
if fork <= head {
|
||||
// Fork already passed, checksum the previous hash and the fork number
|
||||
hash = checksumUpdate(hash, fork)
|
||||
continue
|
||||
}
|
||||
next = fork
|
||||
break
|
||||
}
|
||||
if next == 0 {
|
||||
return checksumToBytes(hash)
|
||||
} else {
|
||||
return checksumToBytes(checksumUpdate(hash, next))
|
||||
}
|
||||
}
|
||||
|
||||
// NewFilter creates a filter that returns if a fork ID should be rejected or notI
|
||||
// based on the local chain's status.
|
||||
func NewFilter(config *params.ChainConfig, genesis common.Hash, head func() uint64) Filter {
|
||||
|
@ -198,6 +198,10 @@ func (sdb *IntraBlockState) GetLogs(hash common.Hash) []*types.Log {
|
||||
return sdb.logs[hash]
|
||||
}
|
||||
|
||||
func (sdb *IntraBlockState) BlockHash() common.Hash {
|
||||
return sdb.bhash
|
||||
}
|
||||
|
||||
func (sdb *IntraBlockState) Logs() []*types.Log {
|
||||
var logs []*types.Log
|
||||
for _, lgs := range sdb.logs {
|
||||
|
15
core/systemcontracts/parlia/const.go
Normal file
15
core/systemcontracts/parlia/const.go
Normal file
@ -0,0 +1,15 @@
|
||||
package systemcontracts
|
||||
|
||||
const (
|
||||
// genesis contracts
|
||||
ValidatorContract = "0x0000000000000000000000000000000000001000"
|
||||
SlashContract = "0x0000000000000000000000000000000000001001"
|
||||
SystemRewardContract = "0x0000000000000000000000000000000000001002"
|
||||
LightClientContract = "0x0000000000000000000000000000000000001003"
|
||||
TokenHubContract = "0x0000000000000000000000000000000000001004"
|
||||
RelayerIncentivizeContract = "0x0000000000000000000000000000000000001005"
|
||||
RelayerHubContract = "0x0000000000000000000000000000000000001006"
|
||||
GovHubContract = "0x0000000000000000000000000000000000001007"
|
||||
TokenManagerContract = "0x0000000000000000000000000000000000001008"
|
||||
CrossChainContract = "0x0000000000000000000000000000000000002000"
|
||||
)
|
@ -28,6 +28,7 @@ const (
|
||||
MimetypeDataWithValidator = "data/validator"
|
||||
MimetypeTypedData = "data/typed"
|
||||
MimetypeClique = "application/x-clique-header"
|
||||
MimetypeParlia = "application/x-parlia-header"
|
||||
MimetypeTextPlain = "text/plain"
|
||||
)
|
||||
|
||||
|
@ -196,6 +196,8 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere
|
||||
|
||||
if chainConfig.Clique != nil {
|
||||
consensusConfig = &config.Clique
|
||||
} else if chainConfig.Parlia != nil {
|
||||
consensusConfig = &config.Parlia
|
||||
} else if chainConfig.Aura != nil {
|
||||
config.Aura.Etherbase = config.Miner.Etherbase
|
||||
consensusConfig = &config.Aura
|
||||
@ -203,7 +205,7 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere
|
||||
consensusConfig = &config.Ethash
|
||||
}
|
||||
|
||||
backend.engine = ethconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify)
|
||||
backend.engine = ethconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, backend.genesisHash)
|
||||
|
||||
log.Info("Initialising Ethereum protocol", "network", config.NetworkID)
|
||||
|
||||
|
@ -36,6 +36,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/core"
|
||||
"github.com/ledgerwatch/erigon/eth/gasprice"
|
||||
"github.com/ledgerwatch/erigon/params"
|
||||
@ -159,6 +160,7 @@ type Config struct {
|
||||
|
||||
Clique params.ConsensusSnapshotConfig
|
||||
Aura params.AuRaConfig
|
||||
Parlia params.ParliaConfig
|
||||
|
||||
// Transaction pool options
|
||||
TxPool core.TxPoolConfig
|
||||
@ -180,7 +182,7 @@ type Config struct {
|
||||
SyncLoopThrottle time.Duration
|
||||
}
|
||||
|
||||
func CreateConsensusEngine(chainConfig *params.ChainConfig, logger log.Logger, config interface{}, notify []string, noverify bool) consensus.Engine {
|
||||
func CreateConsensusEngine(chainConfig *params.ChainConfig, logger log.Logger, config interface{}, notify []string, noverify bool, genesisHash common.Hash) consensus.Engine {
|
||||
var eng consensus.Engine
|
||||
|
||||
switch consensusCfg := config.(type) {
|
||||
@ -210,6 +212,10 @@ func CreateConsensusEngine(chainConfig *params.ChainConfig, logger log.Logger, c
|
||||
if chainConfig.Clique != nil {
|
||||
eng = clique.New(chainConfig, consensusCfg, db.OpenDatabase(consensusCfg.DBPath, logger, consensusCfg.InMemory))
|
||||
}
|
||||
case *params.ParliaConfig:
|
||||
if chainConfig.Parlia != nil {
|
||||
eng = parlia.New(chainConfig, db.OpenDatabase(consensusCfg.DBPath, logger, consensusCfg.InMemory), genesisHash)
|
||||
}
|
||||
case *params.AuRaConfig:
|
||||
if chainConfig.Aura != nil {
|
||||
var err error
|
||||
|
@ -107,7 +107,7 @@ func SpawnMiningExecStage(s *StageState, tx kv.RwTx, cfg MiningExecCfg, quit <-c
|
||||
}
|
||||
}
|
||||
|
||||
if err := core.FinalizeBlockExecution(cfg.engine, stateReader, current.Header, current.Txs, current.Uncles, stateWriter, &cfg.chainConfig, ibs, nil, nil, nil); err != nil {
|
||||
if err := core.FinalizeBlockExecution(cfg.engine, stateReader, current.Header, current.Txs, current.Uncles, stateWriter, &cfg.chainConfig, ibs, nil, nil, nil, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
10
go.mod
10
go.mod
@ -11,6 +11,7 @@ require (
|
||||
github.com/btcsuite/btcd v0.21.0-beta
|
||||
github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2
|
||||
github.com/consensys/gnark-crypto v0.4.0
|
||||
github.com/cosmos/iavl v0.12.2
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
@ -20,6 +21,7 @@ require (
|
||||
github.com/fatih/color v1.12.0
|
||||
github.com/fjl/gencodec v0.0.0-20191126094850-e283372f291f
|
||||
github.com/flanglet/kanzi-go v1.9.0
|
||||
github.com/fortytw2/leaktest v1.3.0 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
github.com/goccy/go-json v0.7.4
|
||||
github.com/gofrs/flock v0.8.1
|
||||
@ -32,6 +34,7 @@ require (
|
||||
github.com/holiman/uint256 v1.2.0
|
||||
github.com/huin/goupnp v1.0.1-0.20210626160114-33cdcbb30dda
|
||||
github.com/jackpal/go-nat-pmp v1.0.2
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/julienschmidt/httprouter v1.3.0
|
||||
github.com/kevinburke/go-bindata v3.21.0+incompatible
|
||||
@ -39,13 +42,18 @@ require (
|
||||
github.com/ledgerwatch/log/v3 v3.4.0
|
||||
github.com/ledgerwatch/secp256k1 v1.0.0
|
||||
github.com/logrusorgru/aurora/v3 v3.0.0
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/pelletier/go-toml v1.9.4
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.6
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 // indirect
|
||||
github.com/rs/cors v1.8.0
|
||||
github.com/shirou/gopsutil/v3 v3.21.11
|
||||
github.com/spf13/cobra v1.2.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect
|
||||
github.com/tendermint/go-amino v0.14.1
|
||||
github.com/tendermint/tendermint v0.31.11
|
||||
github.com/torquem-ch/mdbx-go v0.22.2
|
||||
github.com/ugorji/go/codec v1.1.13
|
||||
github.com/ugorji/go/codec/codecgen v1.1.13
|
||||
@ -61,7 +69,7 @@ require (
|
||||
google.golang.org/grpc v1.42.0
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b
|
||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6
|
||||
pgregory.net/rapid v0.4.7
|
||||
)
|
||||
|
35
go.sum
35
go.sum
@ -73,6 +73,7 @@ github.com/VictoriaMetrics/fastcache v1.7.0 h1:E6GibaGI685TafrI7E/QqZPkMsOzRw+3g
|
||||
github.com/VictoriaMetrics/fastcache v1.7.0/go.mod h1:n7Sl+ioh/HlWeYHLSIBIE8TcZFHg/+xgvomWSS5xuEE=
|
||||
github.com/VictoriaMetrics/metrics v1.18.1 h1:OZ0+kTTto8oPfHnVAnTOoyl0XlRhRkoQrD2n2cOuRw0=
|
||||
github.com/VictoriaMetrics/metrics v1.18.1/go.mod h1:ArjwVz7WpgpegX/JpB0zpNF2h2232kErkEnzH1sxMmA=
|
||||
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
@ -240,6 +241,7 @@ github.com/benbjohnson/immutable v0.3.0 h1:TVRhuZx2wG9SZ0LRdqlbs9S5BZ6Y24hJEHTCg
|
||||
github.com/benbjohnson/immutable v0.3.0/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
|
||||
@ -256,6 +258,7 @@ github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796Zt
|
||||
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts=
|
||||
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
||||
@ -297,6 +300,8 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cosmos/iavl v0.12.2 h1:8EIiYRY5ewl+Ml76B6h3BLga3cn2DuDsm4exxw5Ejro=
|
||||
github.com/cosmos/iavl v0.12.2/go.mod h1:5paARKGkQVKis4t9KbBnXTKdzl+sdDAhR3rIp+iAZzs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
@ -342,6 +347,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM=
|
||||
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||
@ -351,6 +357,8 @@ github.com/fjl/gencodec v0.0.0-20191126094850-e283372f291f/go.mod h1:q+7Z5oyy8cv
|
||||
github.com/flanglet/kanzi-go v1.9.0 h1:bhpFJaGIKGio575OO6mWFec658OKKt7DKS9kMRSl6/U=
|
||||
github.com/flanglet/kanzi-go v1.9.0/go.mod h1:/sUSVgDcbjsisuW42GPDgaMqvJ0McZERNICnD7b1nRA=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
@ -384,10 +392,12 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
@ -409,6 +419,7 @@ github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFG
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
@ -574,6 +585,8 @@ github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
|
||||
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
@ -636,6 +649,7 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2
|
||||
github.com/lukechampine/stm v0.0.0-20191022212748-05486c32d236/go.mod h1:wTLsd5FC9rts7GkMpsPGk64CIuea+03yaLAp19Jmlg8=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/qpack v0.2.0/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
|
||||
@ -644,6 +658,7 @@ github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwm
|
||||
github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.0/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
||||
github.com/matryer/moq v0.2.3 h1:Q06vEqnBYjjfx5KKgHfYRKE/lvlRu+Nj+xodG4YdHnU=
|
||||
github.com/matryer/moq v0.2.3/go.mod h1:9RtPYjTnH1bSBIkpvtHkFN7nbWAnO7oRpdJkEIn6UtE=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
@ -662,6 +677,7 @@ github.com/mattn/go-sqlite3 v1.7.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOq
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.13.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v2.0.2+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
@ -695,6 +711,8 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
@ -832,6 +850,7 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU=
|
||||
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
@ -839,6 +858,7 @@ github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
@ -846,6 +866,7 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM=
|
||||
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
@ -857,12 +878,15 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
|
||||
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.3.0 h1:Uehi/mxLK0eiUc0H0++5tpMGTexB8wZ598MIgU8VpDM=
|
||||
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.2/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.6 h1:W2wnISJifyda0x/RXq15Qjrsu9iOhX2gy4+Ku+owylw=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.6/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 h1:dY6ETXrvDG7Sa4vE8ZQG4yqWg6UnOcbqTAahkV813vQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
@ -953,7 +977,13 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/syncthing/syncthing v0.14.48-rc.4/go.mod h1:nw3siZwHPA6M8iSfjDCWQ402eqvEIasMQOE8nFOxy7M=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/tendermint/go-amino v0.14.1 h1:o2WudxNfdLNBwMyl2dqOJxiro5rfrEaU0Ugs6offJMk=
|
||||
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
|
||||
github.com/tendermint/tendermint v0.31.11 h1:TIs//4WfEAG4TOZc2eUfJPI3T8KrywXQCCPnGAaM1Wo=
|
||||
github.com/tendermint/tendermint v0.31.11/go.mod h1:ymcPyWblXCplCPQjbOYbrF1fWnpslATMVqiGgWbZrlc=
|
||||
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tinylib/msgp v1.1.1/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
@ -1148,6 +1178,7 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
@ -1255,6 +1286,7 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -1510,8 +1542,9 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
|
@ -170,7 +170,7 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit
|
||||
|
||||
if !vmConfig.ReadOnly {
|
||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||
if _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil, nil, nil, nil); err != nil {
|
||||
if _, _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil, nil, nil, nil); err != nil {
|
||||
return nil, fmt.Errorf("finalize of block %d failed: %w", block.NumberU64(), err)
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,7 @@ var (
|
||||
PetersburgBlock: big.NewInt(7_280_000),
|
||||
IstanbulBlock: big.NewInt(9_069_000),
|
||||
MuirGlacierBlock: big.NewInt(9_200_000),
|
||||
RamanujanBlock: nil,
|
||||
BerlinBlock: big.NewInt(12_244_000),
|
||||
LondonBlock: big.NewInt(12_965_000),
|
||||
ArrowGlacierBlock: big.NewInt(13_773_000),
|
||||
@ -108,6 +109,7 @@ var (
|
||||
PetersburgBlock: big.NewInt(4_939_394),
|
||||
IstanbulBlock: big.NewInt(6_485_846),
|
||||
MuirGlacierBlock: big.NewInt(7_117_117),
|
||||
RamanujanBlock: nil,
|
||||
BerlinBlock: big.NewInt(9_812_189),
|
||||
LondonBlock: big.NewInt(10_499_401),
|
||||
Ethash: new(EthashConfig),
|
||||
@ -128,6 +130,7 @@ var (
|
||||
ByzantiumBlock: big.NewInt(1_035_301),
|
||||
ConstantinopleBlock: big.NewInt(3_660_663),
|
||||
PetersburgBlock: big.NewInt(4_321_234),
|
||||
RamanujanBlock: nil,
|
||||
IstanbulBlock: big.NewInt(5_435_345),
|
||||
MuirGlacierBlock: nil,
|
||||
BerlinBlock: big.NewInt(8_290_928),
|
||||
@ -421,12 +424,15 @@ type ChainConfig struct {
|
||||
LondonBlock *big.Int `json:"londonBlock,omitempty"` // London switch block (nil = no fork, 0 = already on london)
|
||||
ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // EIP-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||
|
||||
RamanujanBlock *big.Int `json:"ramanujanBlock,omitempty"` // ramanujanBlock switch block (nil = no fork, 0 = already activated)
|
||||
|
||||
// EIP-3675: Upgrade consensus to Proof-of-Stake
|
||||
TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"` // The merge happens when terminal total difficulty is reached
|
||||
// Various consensus engines
|
||||
Ethash *EthashConfig `json:"ethash,omitempty"`
|
||||
Clique *CliqueConfig `json:"clique,omitempty"`
|
||||
Aura *AuRaConfig `json:"aura,omitempty"`
|
||||
Parlia *ParliaConfig `json:"parlia,omitempty"`
|
||||
}
|
||||
|
||||
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
|
||||
@ -455,6 +461,19 @@ func (c *CliqueConfig) String() string {
|
||||
return "clique"
|
||||
}
|
||||
|
||||
// ParliaConfig is the consensus engine configs for proof-of-staked-authority based sealing.
|
||||
type ParliaConfig struct {
|
||||
DBPath string
|
||||
InMemory bool
|
||||
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
|
||||
Epoch uint64 `json:"epoch"` // Epoch length to update validatorSet
|
||||
}
|
||||
|
||||
// String implements the stringer interface, returning the consensus engine details.
|
||||
func (b *ParliaConfig) String() string {
|
||||
return "parlia"
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface.
|
||||
func (c *ChainConfig) String() string {
|
||||
var engine interface{}
|
||||
@ -463,6 +482,8 @@ func (c *ChainConfig) String() string {
|
||||
engine = c.Ethash
|
||||
case c.Clique != nil:
|
||||
engine = c.Clique
|
||||
case c.Parlia != nil:
|
||||
engine = c.Parlia
|
||||
default:
|
||||
engine = "unknown"
|
||||
}
|
||||
@ -544,11 +565,21 @@ func (c *ChainConfig) IsByzantium(num uint64) bool {
|
||||
return isForked(c.ByzantiumBlock, num)
|
||||
}
|
||||
|
||||
// IsByzantium returns whether num is either equal to the Byzantium fork block or greater.
|
||||
func (c *ChainConfig) IsByzantiumBigInt(num *big.Int) bool {
|
||||
return configNumEqual(c.ByzantiumBlock, num)
|
||||
}
|
||||
|
||||
// IsConstantinople returns whether num is either equal to the Constantinople fork block or greater.
|
||||
func (c *ChainConfig) IsConstantinople(num uint64) bool {
|
||||
return isForked(c.ConstantinopleBlock, num)
|
||||
}
|
||||
|
||||
// IsRamanujan returns whether num is either equal to the IsRamanujan fork block or greater.
|
||||
func (c *ChainConfig) IsRamanujanBigInt(num *big.Int) bool {
|
||||
return configNumEqual(c.RamanujanBlock, num)
|
||||
}
|
||||
|
||||
// IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater.
|
||||
func (c *ChainConfig) IsMuirGlacier(num uint64) bool {
|
||||
return isForked(c.MuirGlacierBlock, num)
|
||||
|
Loading…
Reference in New Issue
Block a user