mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-21 19:20:39 +00:00
Add support for PulseChain
Thanks @bretep for the original integration.
This commit is contained in:
parent
aa3a804757
commit
75db06fa1d
21
Dockerfile
21
Dockerfile
@ -42,17 +42,6 @@ FROM docker.io/library/alpine:3.17
|
||||
RUN apk add --no-cache ca-certificates libstdc++ tzdata
|
||||
RUN apk add --no-cache curl jq bind-tools
|
||||
|
||||
# Setup user and group
|
||||
#
|
||||
# from the perspective of the container, uid=1000, gid=1000 is a sensible choice
|
||||
# (mimicking Ubuntu Server), but if caller creates a .env (example in repo root),
|
||||
# these defaults will get overridden when make calls docker-compose
|
||||
ARG UID=1000
|
||||
ARG GID=1000
|
||||
RUN adduser -D -u $UID -g $GID erigon
|
||||
USER erigon
|
||||
RUN mkdir -p ~/.local/share/erigon
|
||||
|
||||
# copy compiled artifacts from builder
|
||||
## first do the mdbx ones - since these wont change as often
|
||||
COPY --from=tools-builder /app/build/bin/mdbx_chk /usr/local/bin/mdbx_chk
|
||||
@ -98,13 +87,13 @@ ARG BUILD_DATE
|
||||
ARG VCS_REF
|
||||
ARG VERSION
|
||||
LABEL org.label-schema.build-date=$BUILD_DATE \
|
||||
org.label-schema.description="Erigon Ethereum Client" \
|
||||
org.label-schema.name="Erigon" \
|
||||
org.label-schema.description="Erigon Ethereum Client with PulseChain" \
|
||||
org.label-schema.name="Erigon PulseChain" \
|
||||
org.label-schema.schema-version="1.0" \
|
||||
org.label-schema.url="https://torquem.ch" \
|
||||
org.label-schema.url="https://gitlab.com/pulsechaincom/erigon-pulse" \
|
||||
org.label-schema.vcs-ref=$VCS_REF \
|
||||
org.label-schema.vcs-url="https://github.com/ledgerwatch/erigon.git" \
|
||||
org.label-schema.vendor="Torquem" \
|
||||
org.label-schema.vcs-url="https://gitlab.com/pulsechaincom/erigon-pulse.git" \
|
||||
org.label-schema.vendor="PulseChain" \
|
||||
org.label-schema.version=$VERSION
|
||||
|
||||
ENTRYPOINT ["erigon"]
|
||||
|
1
Makefile
1
Makefile
@ -79,6 +79,7 @@ docker: validate_docker_build_args git-submodules
|
||||
--build-arg VERSION=${GIT_TAG} \
|
||||
--build-arg UID=${DOCKER_UID} \
|
||||
--build-arg GID=${DOCKER_GID} \
|
||||
--build-arg DEPLOY_TOKEN=${DEPLOY_TOKEN} \
|
||||
${DOCKER_FLAGS} \
|
||||
.
|
||||
|
||||
|
@ -35,6 +35,7 @@ var (
|
||||
maxPendPeers int
|
||||
healthCheck bool
|
||||
metrics bool
|
||||
chainName string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -55,6 +56,7 @@ func init() {
|
||||
rootCmd.Flags().IntVar(&maxPendPeers, utils.MaxPendingPeersFlag.Name, utils.MaxPendingPeersFlag.Value, utils.MaxPendingPeersFlag.Usage)
|
||||
rootCmd.Flags().BoolVar(&healthCheck, utils.HealthCheckFlag.Name, false, utils.HealthCheckFlag.Usage)
|
||||
rootCmd.Flags().BoolVar(&metrics, utils.MetricsEnabledFlag.Name, false, utils.MetricsEnabledFlag.Usage)
|
||||
rootCmd.Flags().StringVar(&chainName, utils.ChainFlag.Name, utils.ChainFlag.Value, utils.ChainFlag.Usage)
|
||||
|
||||
if err := rootCmd.MarkFlagDirname(utils.DataDirFlag.Name); err != nil {
|
||||
panic(err)
|
||||
@ -88,6 +90,7 @@ var rootCmd = &cobra.Command{
|
||||
protocol,
|
||||
allowedPorts,
|
||||
metrics,
|
||||
chainName,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -97,7 +97,7 @@ var (
|
||||
}
|
||||
ChainFlag = cli.StringFlag{
|
||||
Name: "chain",
|
||||
Usage: "name of the network to join",
|
||||
Usage: "Name of the network to join",
|
||||
Value: networkname.MainnetChainName,
|
||||
}
|
||||
IdentityFlag = cli.StringFlag{
|
||||
@ -1062,6 +1062,7 @@ func NewP2PConfig(
|
||||
protocol uint,
|
||||
allowedPorts []uint,
|
||||
metricsEnabled bool,
|
||||
chainName string,
|
||||
) (*p2p.Config, error) {
|
||||
var enodeDBPath string
|
||||
switch protocol {
|
||||
@ -1092,6 +1093,7 @@ func NewP2PConfig(
|
||||
AllowedPorts: allowedPorts,
|
||||
TmpDir: dirs.Tmp,
|
||||
MetricsEnabled: metricsEnabled,
|
||||
ChainName: chainName,
|
||||
}
|
||||
if netRestrict != "" {
|
||||
cfg.NetRestrict = new(netutil.Netlist)
|
||||
@ -1771,7 +1773,7 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis libcommon.Hash) {
|
||||
return // already set through flags/config
|
||||
}
|
||||
protocol := "all"
|
||||
if url := params.KnownDNSNetwork(genesis, protocol); url != "" {
|
||||
if url := params.KnownDNSNetwork(genesis, cfg.NetworkID, protocol); url != "" {
|
||||
cfg.EthDiscoveryURLs = []string{url}
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +100,10 @@ func DataDirForNetwork(datadir string, network string) string {
|
||||
return networkDataDirCheckingLegacy(datadir, "gnosis")
|
||||
case networkname.ChiadoChainName:
|
||||
return networkDataDirCheckingLegacy(datadir, "chiado")
|
||||
case networkname.PulsechainChainName:
|
||||
return networkDataDirCheckingLegacy(datadir, "pulsechain")
|
||||
case networkname.PulsechainTestnetChainName:
|
||||
return networkDataDirCheckingLegacy(datadir, "pulsechain-testnet")
|
||||
|
||||
default:
|
||||
return datadir
|
||||
|
@ -39,6 +39,7 @@ import (
|
||||
"github.com/ledgerwatch/erigon/core/state"
|
||||
"github.com/ledgerwatch/erigon/core/types"
|
||||
"github.com/ledgerwatch/erigon/params"
|
||||
"github.com/ledgerwatch/erigon/pulse"
|
||||
"github.com/ledgerwatch/erigon/rlp"
|
||||
)
|
||||
|
||||
@ -294,6 +295,8 @@ func (ethash *Ethash) CalcDifficulty(chain consensus.ChainHeaderReader, time, pa
|
||||
func CalcDifficulty(config *chain.Config, time, parentTime uint64, parentDifficulty *big.Int, parentNumber uint64, parentUncleHash libcommon.Hash) *big.Int {
|
||||
next := parentNumber + 1
|
||||
switch {
|
||||
case config.IsPrimordialPulseBlock(next):
|
||||
return chain.PulseChainTTDOffset
|
||||
case config.IsGrayGlacier(next):
|
||||
return calcDifficultyEip5133(time, parentTime, parentDifficulty, parentNumber, parentUncleHash)
|
||||
case config.IsArrowGlacier(next):
|
||||
@ -562,6 +565,11 @@ func (ethash *Ethash) Finalize(config *chain.Config, header *types.Header, state
|
||||
txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal,
|
||||
chain consensus.ChainReader, syscall consensus.SystemCall, logger log.Logger,
|
||||
) (types.Transactions, types.Receipts, error) {
|
||||
// Apply fork changes on PrimordialPulse block
|
||||
if cfg := chain.Config(); cfg.IsPrimordialPulseBlock(header.Number.Uint64()) {
|
||||
pulse.PrimordialPulseFork(state, cfg.PulseChain)
|
||||
}
|
||||
|
||||
// Accumulate any block and uncle rewards and commit the final state root
|
||||
accumulateRewards(config, state, header, uncles)
|
||||
return txs, r, nil
|
||||
|
@ -82,8 +82,8 @@ func (s *Merge) VerifyHeader(chain consensus.ChainHeaderReader, header *types.He
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !reached {
|
||||
// Not verifying seals if the TTD is passed
|
||||
if !reached && (chain.Config().PulseChain == nil || !misc.IsPoSHeader(header)) {
|
||||
// Delegate non-PoS block to eth1 verification
|
||||
return s.eth1Engine.VerifyHeader(chain, header, !chain.Config().TerminalTotalDifficultyPassed)
|
||||
}
|
||||
// Short circuit if the parent is not known
|
||||
|
@ -121,12 +121,18 @@ func WriteGenesisBlock(tx kv.RwTx, genesis *types.Genesis, overrideCancunTime *b
|
||||
return genesis.Config, block, nil
|
||||
}
|
||||
|
||||
// Assume mainnet chainId first
|
||||
chainId := params.MainnetChainConfig.ChainID.Uint64()
|
||||
|
||||
// Check whether the genesis block is already written.
|
||||
if genesis != nil {
|
||||
block, _, err1 := GenesisToBlock(genesis, tmpDir, logger)
|
||||
if err1 != nil {
|
||||
return genesis.Config, nil, err1
|
||||
}
|
||||
// Use the incoming chainID for building chain config.
|
||||
// Allows for mainnet genesis w/ pulsechain config.
|
||||
chainId = genesis.Config.ChainID.Uint64()
|
||||
hash := block.Hash()
|
||||
if hash != storedHash {
|
||||
return genesis.Config, block, &types.GenesisMismatchError{Stored: storedHash, New: hash}
|
||||
@ -140,13 +146,18 @@ func WriteGenesisBlock(tx kv.RwTx, genesis *types.Genesis, overrideCancunTime *b
|
||||
return genesis.Config, nil, err
|
||||
}
|
||||
}
|
||||
storedCfg, storedErr := rawdb.ReadChainConfig(tx, storedHash)
|
||||
if storedErr == nil && storedCfg != nil {
|
||||
// Use the existing chainID for building chain config.
|
||||
// Allows for mainnet genesis w/ pulsechain config.
|
||||
chainId = storedCfg.ChainID.Uint64()
|
||||
}
|
||||
// Get the existing chain configuration.
|
||||
newCfg := genesis.ConfigOrDefault(storedHash)
|
||||
newCfg := genesis.ConfigOrDefault(storedHash, chainId)
|
||||
applyOverrides(newCfg)
|
||||
if err := newCfg.CheckConfigForkOrder(); err != nil {
|
||||
return newCfg, nil, err
|
||||
}
|
||||
storedCfg, storedErr := rawdb.ReadChainConfig(tx, storedHash)
|
||||
if storedErr != nil && newCfg.Bor == nil {
|
||||
return newCfg, nil, storedErr
|
||||
}
|
||||
@ -457,6 +468,28 @@ func ChiadoGenesisBlock() *types.Genesis {
|
||||
}
|
||||
}
|
||||
|
||||
func PulsechainGenesisBlock() *types.Genesis {
|
||||
return &types.Genesis{
|
||||
Config: params.PulsechainChainConfig,
|
||||
Nonce: 66,
|
||||
ExtraData: hexutil.MustDecode("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"),
|
||||
GasLimit: 5000,
|
||||
Difficulty: big.NewInt(17179869184),
|
||||
Alloc: readPrealloc("allocs/mainnet.json"),
|
||||
}
|
||||
}
|
||||
|
||||
func PulsechainTestnetGenesisBlock() *types.Genesis {
|
||||
return &types.Genesis{
|
||||
Config: params.PulsechainTestnetChainConfig,
|
||||
Nonce: 66,
|
||||
ExtraData: hexutil.MustDecode("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"),
|
||||
GasLimit: 5000,
|
||||
Difficulty: big.NewInt(17179869184),
|
||||
Alloc: readPrealloc("allocs/mainnet.json"),
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-calculated version of:
|
||||
//
|
||||
// DevnetSignPrivateKey = crypto.HexToECDSA(sha256.Sum256([]byte("erigon devnet key")))
|
||||
@ -675,6 +708,10 @@ func GenesisBlockByChainName(chain string) *types.Genesis {
|
||||
return GnosisGenesisBlock()
|
||||
case networkname.ChiadoChainName:
|
||||
return ChiadoGenesisBlock()
|
||||
case networkname.PulsechainChainName:
|
||||
return PulsechainGenesisBlock()
|
||||
case networkname.PulsechainTestnetChainName:
|
||||
return PulsechainTestnetGenesisBlock()
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ import (
|
||||
var analysisBlocks = map[string][]uint64{
|
||||
networkname.MainnetChainName: {5_800_596, 6_426_298, 6_426_432, 11_079_912, 13_119_520, 15_081_051},
|
||||
networkname.BorMainnetChainName: {29_447_463},
|
||||
networkname.PulsechainChainName: {5_800_596, 6_426_298, 6_426_432, 11_079_912, 13_119_520, 15_081_051},
|
||||
networkname.PulsechainTestnetChainName: {5_800_596, 6_426_298, 6_426_432, 11_079_912, 13_119_520, 15_081_051},
|
||||
}
|
||||
|
||||
func SkipAnalysis(config *chain.Config, blockNumber uint64) bool {
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ledgerwatch/erigon-lib/chain"
|
||||
"github.com/ledgerwatch/erigon-lib/chain/networkname"
|
||||
"github.com/ledgerwatch/erigon-lib/common"
|
||||
"github.com/ledgerwatch/erigon-lib/common/hexutility"
|
||||
|
||||
@ -165,12 +166,23 @@ func (e *GenesisMismatchError) Error() string {
|
||||
}
|
||||
return fmt.Sprintf("database contains incompatible genesis (try with --chain=%s)", config.ChainName)
|
||||
}
|
||||
func (g *Genesis) ConfigOrDefault(genesisHash common.Hash) *chain.Config {
|
||||
func (g *Genesis) ConfigOrDefault(genesisHash common.Hash, chainId uint64) *chain.Config {
|
||||
if g != nil {
|
||||
return g.Config
|
||||
}
|
||||
|
||||
config := params.ChainConfigByGenesisHash(genesisHash)
|
||||
var config *chain.Config
|
||||
pulseChainConfig := params.ChainConfigByChainName(networkname.PulsechainChainName)
|
||||
pulseChainTestnetConfig := params.ChainConfigByChainName(networkname.PulsechainTestnetChainName)
|
||||
switch chainId {
|
||||
case pulseChainConfig.ChainID.Uint64():
|
||||
config = pulseChainConfig
|
||||
case pulseChainTestnetConfig.ChainID.Uint64():
|
||||
config = pulseChainTestnetConfig
|
||||
default:
|
||||
config = params.ChainConfigByGenesisHash(genesisHash)
|
||||
}
|
||||
|
||||
if config != nil {
|
||||
return config
|
||||
} else {
|
||||
|
@ -42,6 +42,12 @@ func MakeSigner(config *chain.Config, blockNumber uint64, blockTime uint64) *Sig
|
||||
if overflow {
|
||||
panic(fmt.Errorf("chainID higher than 2^256-1"))
|
||||
}
|
||||
|
||||
if config.PrimordialPulseAhead(blockNumber) {
|
||||
// ethereum mainnet chainID is 1
|
||||
// required to validate transactions on mainnet
|
||||
chainId.SetOne()
|
||||
}
|
||||
}
|
||||
signer.unprotected = true
|
||||
switch {
|
||||
|
@ -17,6 +17,7 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
@ -97,13 +98,24 @@ type EVM struct {
|
||||
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
|
||||
// only ever be used *once*.
|
||||
func NewEVM(blockCtx evmtypes.BlockContext, txCtx evmtypes.TxContext, state evmtypes.IntraBlockState, chainConfig *chain.Config, vmConfig Config) *EVM {
|
||||
flexChainConfig := chainConfig
|
||||
|
||||
if flexChainConfig.PrimordialPulseAhead(blockCtx.BlockNumber) {
|
||||
// create a shallow of chainConfig struct and set to ethereum mainnet
|
||||
chainCfgCpy := *chainConfig
|
||||
chainCfgCpy.ChainID = big.NewInt(1)
|
||||
|
||||
// use the new chainCfgCpy
|
||||
flexChainConfig = &chainCfgCpy
|
||||
}
|
||||
|
||||
evm := &EVM{
|
||||
Context: blockCtx,
|
||||
TxContext: txCtx,
|
||||
intraBlockState: state,
|
||||
config: vmConfig,
|
||||
chainConfig: chainConfig,
|
||||
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Time),
|
||||
chainConfig: flexChainConfig,
|
||||
chainRules: flexChainConfig.Rules(blockCtx.BlockNumber, blockCtx.Time),
|
||||
}
|
||||
|
||||
evm.interpreter = NewEVMInterpreter(evm, vmConfig)
|
||||
|
@ -68,6 +68,9 @@ type Config struct {
|
||||
CancunTime *big.Int `json:"cancunTime,omitempty"`
|
||||
PragueTime *big.Int `json:"pragueTime,omitempty"`
|
||||
|
||||
// PulseChain fork blocks
|
||||
PrimordialPulseBlock *big.Int `json:"primordialPulseBlock,omitempty"` // PrimordialPulseBlock switch block (nil = no fork, 0 = already activated)
|
||||
|
||||
// Optional EIP-4844 parameters
|
||||
MinBlobGasPrice *uint64 `json:"minBlobGasPrice,omitempty"`
|
||||
MaxBlobGasPerBlock *uint64 `json:"maxBlobGasPerBlock,omitempty"`
|
||||
@ -84,6 +87,8 @@ type Config struct {
|
||||
|
||||
Bor BorConfig `json:"-"`
|
||||
BorJSON json.RawMessage `json:"bor,omitempty"`
|
||||
|
||||
PulseChain *PulseChainConfig `json:"pulseChain,omitempty"`
|
||||
}
|
||||
|
||||
type BorConfig interface {
|
||||
@ -97,7 +102,7 @@ type BorConfig interface {
|
||||
func (c *Config) String() string {
|
||||
engine := c.getEngine()
|
||||
|
||||
return fmt.Sprintf("{ChainID: %v, Homestead: %v, DAO: %v, Tangerine Whistle: %v, Spurious Dragon: %v, Byzantium: %v, Constantinople: %v, Petersburg: %v, Istanbul: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Gray Glacier: %v, Terminal Total Difficulty: %v, Merge Netsplit: %v, Shanghai: %v, Cancun: %v, Prague: %v, Engine: %v}",
|
||||
return fmt.Sprintf("{ChainID: %v, Homestead: %v, DAO: %v, Tangerine Whistle: %v, Spurious Dragon: %v, Byzantium: %v, Constantinople: %v, Petersburg: %v, Istanbul: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Gray Glacier: %v, Primordial Pulse: %v, Terminal Total Difficulty: %v, Merge Netsplit: %v, Shanghai: %v, Cancun: %v, Prague: %v, Engine: %v}",
|
||||
c.ChainID,
|
||||
c.HomesteadBlock,
|
||||
c.DAOForkBlock,
|
||||
@ -112,6 +117,7 @@ func (c *Config) String() string {
|
||||
c.LondonBlock,
|
||||
c.ArrowGlacierBlock,
|
||||
c.GrayGlacierBlock,
|
||||
c.PrimordialPulseBlock,
|
||||
c.TerminalTotalDifficulty,
|
||||
c.MergeNetsplitBlock,
|
||||
c.ShanghaiTime,
|
||||
@ -231,6 +237,17 @@ func (c *Config) IsPrague(time uint64) bool {
|
||||
return isForked(c.PragueTime, time)
|
||||
}
|
||||
|
||||
// IsPrimordialPulseBlock returns whether or not the given block is the primordial pulse block.
|
||||
func (c *Config) IsPrimordialPulseBlock(number uint64) bool {
|
||||
return c.PrimordialPulseBlock != nil && c.PrimordialPulseBlock.Uint64() == number
|
||||
}
|
||||
|
||||
// PrimordialPulseAhead Returns true if there is a PrimordialPulse block in the future, indicating this chain
|
||||
// should still be evaluated using the ethash consensus engine and with mainnet ChainID.
|
||||
func (c *Config) PrimordialPulseAhead(number uint64) bool {
|
||||
return c.PrimordialPulseBlock != nil && c.PrimordialPulseBlock.Uint64() > number
|
||||
}
|
||||
|
||||
func (c *Config) GetBurntContract(num uint64) *common.Address {
|
||||
if len(c.BurntContract) == 0 {
|
||||
return nil
|
||||
@ -363,7 +380,8 @@ func (c *Config) checkCompatible(newcfg *Config, head uint64) *ConfigCompatError
|
||||
if incompatible(c.SpuriousDragonBlock, newcfg.SpuriousDragonBlock, head) {
|
||||
return newCompatError("Spurious Dragon fork block", c.SpuriousDragonBlock, newcfg.SpuriousDragonBlock)
|
||||
}
|
||||
if c.IsSpuriousDragon(head) && !numEqual(c.ChainID, newcfg.ChainID) {
|
||||
// allow mismatching ChainID if there is a PrimordialPulse block ahead
|
||||
if c.IsSpuriousDragon(head) && !numEqual(c.ChainID, newcfg.ChainID) && !newcfg.PrimordialPulseAhead(head) {
|
||||
return newCompatError("EIP155 chain ID", c.SpuriousDragonBlock, newcfg.SpuriousDragonBlock)
|
||||
}
|
||||
if incompatible(c.ByzantiumBlock, newcfg.ByzantiumBlock, head) {
|
||||
@ -400,6 +418,9 @@ func (c *Config) checkCompatible(newcfg *Config, head uint64) *ConfigCompatError
|
||||
if incompatible(c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock, head) {
|
||||
return newCompatError("Merge netsplit block", c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock)
|
||||
}
|
||||
if incompatible(c.PrimordialPulseBlock, newcfg.PrimordialPulseBlock, head) {
|
||||
return newCompatError("PrimordialPulse fork block", c.PrimordialPulseBlock, newcfg.PrimordialPulseBlock)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -506,6 +527,12 @@ func (c *Config) Rules(num uint64, time uint64) *Rules {
|
||||
if chainID == nil {
|
||||
chainID = new(big.Int)
|
||||
}
|
||||
isShanghai := c.IsShanghai(time)
|
||||
if c.PrimordialPulseAhead(num) {
|
||||
// If the PrimordialPulse fork is ahead, derive the `isShanghai` rule
|
||||
// from the Ethereum Mainnet Shanghai timestamp.
|
||||
isShanghai = time >= 1681338455
|
||||
}
|
||||
|
||||
return &Rules{
|
||||
ChainID: new(big.Int).Set(chainID),
|
||||
@ -518,7 +545,7 @@ func (c *Config) Rules(num uint64, time uint64) *Rules {
|
||||
IsIstanbul: c.IsIstanbul(num),
|
||||
IsBerlin: c.IsBerlin(num),
|
||||
IsLondon: c.IsLondon(num),
|
||||
IsShanghai: c.IsShanghai(time) || c.IsAgra(num),
|
||||
IsShanghai: isShanghai || c.IsAgra(num),
|
||||
IsCancun: c.IsCancun(time),
|
||||
IsNapoli: c.IsNapoli(num),
|
||||
IsPrague: c.IsPrague(time),
|
||||
|
@ -13,6 +13,8 @@ const (
|
||||
GnosisChainName = "gnosis"
|
||||
BorE2ETestChain2ValName = "bor-e2e-test-2Val"
|
||||
ChiadoChainName = "chiado"
|
||||
PulsechainChainName = "pulsechain"
|
||||
PulsechainTestnetChainName = "pulsechain-testnet"
|
||||
)
|
||||
|
||||
var All = []string{
|
||||
@ -26,4 +28,6 @@ var All = []string{
|
||||
BorDevnetChainName,
|
||||
GnosisChainName,
|
||||
ChiadoChainName,
|
||||
PulsechainChainName,
|
||||
PulsechainTestnetChainName,
|
||||
}
|
||||
|
25
erigon-lib/chain/pulsechain_config.go
Normal file
25
erigon-lib/chain/pulsechain_config.go
Normal file
@ -0,0 +1,25 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type PulseChainConfig struct {
|
||||
// An optional treasury which will receive allocations during the PrimordialPulseBlock.
|
||||
Treasury *PulseChainTreasury `json:"treasury,omitempty"`
|
||||
}
|
||||
|
||||
// String implements the stringer interface, returning the consensus engine details.
|
||||
func (b *PulseChainConfig) String() string {
|
||||
return "PulseChain"
|
||||
}
|
||||
|
||||
// PulseChainTreasury represents an optional treasury for launching PulseChain testnets.
|
||||
type PulseChainTreasury struct {
|
||||
Addr string `json:"addr"`
|
||||
Balance string `json:"balance"`
|
||||
}
|
||||
|
||||
// PulseChainTTDOffset is a trivially small amount of work added to the Ethereum Mainnet TTD
|
||||
// to allow for un-merging and merging with the PulseChain beacon chain.
|
||||
var PulseChainTTDOffset = big.NewInt(131_072)
|
@ -10,6 +10,7 @@ import (
|
||||
snapshothashes "github.com/ledgerwatch/erigon-snapshot"
|
||||
"github.com/ledgerwatch/erigon-snapshot/webseed"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
pulseSnapshotHashes "gitlab.com/pulsechaincom/erigon-pulse-snapshot"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
@ -23,6 +24,8 @@ var (
|
||||
BorMainnet = fromToml(snapshothashes.BorMainnet)
|
||||
Gnosis = fromToml(snapshothashes.Gnosis)
|
||||
Chiado = fromToml(snapshothashes.Chiado)
|
||||
PulseChainMainnet = fromToml(pulseSnapshotHashes.PulseChainMainnet)
|
||||
PulseChainTestnet = fromToml(snapshothashes.Mainnet)
|
||||
)
|
||||
|
||||
type PreverifiedItem struct {
|
||||
@ -144,6 +147,8 @@ var knownPreverified = map[string]Preverified{
|
||||
networkname.BorMainnetChainName: BorMainnet,
|
||||
networkname.GnosisChainName: Gnosis,
|
||||
networkname.ChiadoChainName: Chiado,
|
||||
networkname.PulsechainChainName: PulseChainMainnet,
|
||||
networkname.PulsechainTestnetChainName: PulseChainTestnet,
|
||||
}
|
||||
|
||||
// KnownCfg return list of preverified hashes for given network, but apply whiteList filter if it's not empty
|
||||
|
@ -74,8 +74,8 @@ func NewFetch(ctx context.Context, sentryClients []direct.SentryClient, pool Poo
|
||||
coreDB: coreDB,
|
||||
db: db,
|
||||
stateChangesClient: stateChangesClient,
|
||||
stateChangesParseCtx: types2.NewTxParseContext(chainID).ChainIDRequired(), //TODO: change ctx if rules changed
|
||||
pooledTxsParseCtx: types2.NewTxParseContext(chainID).ChainIDRequired(),
|
||||
stateChangesParseCtx: types2.NewTxParseContext(chainID, false).ChainIDRequired(), //TODO: change ctx if rules changed
|
||||
pooledTxsParseCtx: types2.NewTxParseContext(chainID, false).ChainIDRequired(),
|
||||
logger: logger,
|
||||
}
|
||||
f.pooledTxsParseCtx.ValidateRLP(f.pool.ValidateSerializedTxn)
|
||||
|
@ -46,7 +46,7 @@ func TestFetch(t *testing.T) {
|
||||
sentryClient := direct.NewSentryClientDirect(direct.ETH66, m)
|
||||
pool := &PoolMock{}
|
||||
|
||||
fetch := NewFetch(ctx, []direct.SentryClient{sentryClient}, pool, &remote.KVClientMock{}, nil, nil, *u256.N1, log.New())
|
||||
fetch := NewFetch(ctx, []direct.SentryClient{sentryClient}, pool, &remote.KVClientMock{}, nil, nil, *u256.N1, log.New(), false)
|
||||
var wg sync.WaitGroup
|
||||
fetch.SetWaitGroup(&wg)
|
||||
m.StreamWg.Add(2)
|
||||
@ -184,7 +184,7 @@ func TestOnNewBlock(t *testing.T) {
|
||||
},
|
||||
}
|
||||
pool := &PoolMock{}
|
||||
fetch := NewFetch(ctx, nil, pool, stateChanges, coreDB, db, *u256.N1, log.New())
|
||||
fetch := NewFetch(ctx, nil, pool, stateChanges, coreDB, db, *u256.N1, log.New(), false)
|
||||
err := fetch.handleStateChanges(ctx, stateChanges)
|
||||
assert.ErrorIs(t, io.EOF, err)
|
||||
assert.Equal(t, 1, len(pool.OnNewBlockCalls()))
|
||||
|
@ -654,7 +654,7 @@ func (p *TxPool) getCachedBlobTxnLocked(tx kv.Tx, hash []byte) (*metaTx, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parseCtx := types.NewTxParseContext(p.chainID)
|
||||
parseCtx := types.NewTxParseContext(p.chainID, false)
|
||||
parseCtx.WithSender(false)
|
||||
txSlot := &types.TxSlot{}
|
||||
parseCtx.ParseTransaction(txn, 0, txSlot, nil, false, true, nil)
|
||||
@ -2048,7 +2048,7 @@ func (p *TxPool) fromDB(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error {
|
||||
}
|
||||
|
||||
txs := types.TxSlots{}
|
||||
parseCtx := types.NewTxParseContext(p.chainID)
|
||||
parseCtx := types.NewTxParseContext(p.chainID, false)
|
||||
parseCtx.WithSender(false)
|
||||
|
||||
i := 0
|
||||
|
@ -199,7 +199,7 @@ func poolsFromFuzzBytes(rawTxNonce, rawValues, rawTips, rawFeeCap, rawSender []b
|
||||
senderIDs[senders.AddressAt(i%senders.Len())] = senderID
|
||||
}
|
||||
txs.Txs = make([]*types.TxSlot, len(txNonce))
|
||||
parseCtx := types.NewTxParseContext(*u256.N1)
|
||||
parseCtx := types.NewTxParseContext(*u256.N1, false)
|
||||
parseCtx.WithSender(false)
|
||||
for i := range txNonce {
|
||||
txs.Txs[i] = &types.TxSlot{
|
||||
@ -314,7 +314,7 @@ func FuzzOnNewBlocks(f *testing.F) {
|
||||
|
||||
cfg := txpoolcfg.DefaultConfig
|
||||
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New(), false)
|
||||
assert.NoError(err)
|
||||
|
||||
err = pool.Start(ctx, db)
|
||||
@ -540,7 +540,7 @@ func FuzzOnNewBlocks(f *testing.F) {
|
||||
check(p2pReceived, types.TxSlots{}, "after_flush")
|
||||
checkNotify(p2pReceived, types.TxSlots{}, "after_flush")
|
||||
|
||||
p2, err := New(ch, coreDB, txpoolcfg.DefaultConfig, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
|
||||
p2, err := New(ch, coreDB, txpoolcfg.DefaultConfig, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New(), false)
|
||||
assert.NoError(err)
|
||||
|
||||
p2.senders = pool.senders // senders are not persisted
|
||||
|
@ -53,7 +53,7 @@ func TestNonceFromAddress(t *testing.T) {
|
||||
|
||||
cfg := txpoolcfg.DefaultConfig
|
||||
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New(), false)
|
||||
assert.NoError(err)
|
||||
require.True(pool != nil)
|
||||
ctx := context.Background()
|
||||
@ -173,7 +173,7 @@ func TestReplaceWithHigherFee(t *testing.T) {
|
||||
|
||||
cfg := txpoolcfg.DefaultConfig
|
||||
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New(), false)
|
||||
assert.NoError(err)
|
||||
require.NotEqual(nil, pool)
|
||||
ctx := context.Background()
|
||||
@ -290,7 +290,7 @@ func TestReverseNonces(t *testing.T) {
|
||||
|
||||
cfg := txpoolcfg.DefaultConfig
|
||||
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New(), false)
|
||||
assert.NoError(err)
|
||||
require.True(pool != nil)
|
||||
ctx := context.Background()
|
||||
@ -417,7 +417,7 @@ func TestTxPoke(t *testing.T) {
|
||||
|
||||
cfg := txpoolcfg.DefaultConfig
|
||||
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New(), false)
|
||||
assert.NoError(err)
|
||||
require.True(pool != nil)
|
||||
ctx := context.Background()
|
||||
@ -682,7 +682,7 @@ func TestShanghaiValidateTx(t *testing.T) {
|
||||
}
|
||||
|
||||
cache := &kvcache.DummyCache{}
|
||||
pool, err := New(ch, coreDB, cfg, cache, *u256.N1, shanghaiTime, nil /* agraBlock */, nil /* cancunTime */, fixedgas.DefaultMaxBlobsPerBlock, nil, logger)
|
||||
pool, err := New(ch, coreDB, cfg, cache, *u256.N1, shanghaiTime, nil /* agraBlock */, nil /* cancunTime */, fixedgas.DefaultMaxBlobsPerBlock, nil, logger, false)
|
||||
asrt.NoError(err)
|
||||
ctx := context.Background()
|
||||
tx, err := coreDB.BeginRw(ctx)
|
||||
@ -728,7 +728,7 @@ func TestBlobTxReplacement(t *testing.T) {
|
||||
db, coreDB := memdb.NewTestPoolDB(t), memdb.NewTestDB(t)
|
||||
cfg := txpoolcfg.DefaultConfig
|
||||
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, common.Big0, nil, common.Big0, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
|
||||
pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, common.Big0, nil, common.Big0, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New(), false)
|
||||
assert.NoError(err)
|
||||
require.True(pool != nil)
|
||||
ctx := context.Background()
|
||||
@ -929,7 +929,7 @@ func makeBlobTx() types.TxSlot {
|
||||
tip, feeCap, blobFeeCap := uint256.NewInt(100_000), uint256.NewInt(200_000), uint256.NewInt(200_000)
|
||||
|
||||
blobTx := types.TxSlot{}
|
||||
tctx := types.NewTxParseContext(*uint256.NewInt(5))
|
||||
tctx := types.NewTxParseContext(*uint256.NewInt(5), false)
|
||||
tctx.WithSender(false)
|
||||
tctx.ParseTransaction(wrapperRlp, 0, &blobTx, nil, false, true, nil)
|
||||
blobTx.BlobHashes = make([]common.Hash, 2)
|
||||
|
@ -182,7 +182,7 @@ func (s *GrpcServer) Add(ctx context.Context, in *txpool_proto.AddRequest) (*txp
|
||||
defer tx.Rollback()
|
||||
|
||||
var slots types.TxSlots
|
||||
parseCtx := types.NewTxParseContext(s.chainID).ChainIDRequired()
|
||||
parseCtx := types.NewTxParseContext(s.chainID, false).ChainIDRequired()
|
||||
parseCtx.ValidateRLP(s.txPool.ValidateSerializedTxn)
|
||||
|
||||
reply := &txpool_proto.AddReply{Imported: make([]txpool_proto.ImportResult, len(in.RlpTxs)), Errors: make([]string, len(in.RlpTxs))}
|
||||
|
@ -64,9 +64,10 @@ type TxParseContext struct {
|
||||
allowPreEip2s bool // Allow s > secp256k1n/2; see EIP-2
|
||||
chainIDRequired bool
|
||||
IsProtected bool
|
||||
allowPulseChainLegacy bool // If allowPulseChainLegacy is true, allow prefork transactions from the Ethereum Mainnet chain.
|
||||
}
|
||||
|
||||
func NewTxParseContext(chainID uint256.Int) *TxParseContext {
|
||||
func NewTxParseContext(chainID uint256.Int, allowPulseChainLegacy bool) *TxParseContext {
|
||||
if chainID.IsZero() {
|
||||
panic("wrong chainID")
|
||||
}
|
||||
@ -74,6 +75,7 @@ func NewTxParseContext(chainID uint256.Int) *TxParseContext {
|
||||
withSender: true,
|
||||
Keccak1: sha3.NewLegacyKeccak256(),
|
||||
Keccak2: sha3.NewLegacyKeccak256(),
|
||||
allowPulseChainLegacy: allowPulseChainLegacy,
|
||||
}
|
||||
|
||||
// behave as of London enabled
|
||||
@ -337,8 +339,14 @@ func (ctx *TxParseContext) parseTransactionBody(payload []byte, pos, p0 int, slo
|
||||
ctx.ChainID.Set(&ctx.cfg.ChainID)
|
||||
}
|
||||
if !ctx.ChainID.Eq(&ctx.cfg.ChainID) {
|
||||
if !ctx.allowPulseChainLegacy {
|
||||
return 0, fmt.Errorf("%w: %s, %d (expected %d)", ErrParseTxn, "invalid chainID", ctx.ChainID.Uint64(), ctx.cfg.ChainID.Uint64())
|
||||
}
|
||||
// If allowPulseChainLegacy, ChainID must be 1 (Ethereum Mainnet).
|
||||
if !ctx.ChainID.Eq(uint256.NewInt(1)) {
|
||||
return 0, fmt.Errorf("%w: %s, %d (expected %d)", ErrParseTxn, "invalid PulseChain chainID", ctx.ChainID.Uint64(), ctx.cfg.ChainID.Uint64())
|
||||
}
|
||||
}
|
||||
}
|
||||
// Next follows the nonce, which we need to parse
|
||||
p, slot.Nonce, err = rlp.U64(payload, p)
|
||||
@ -486,8 +494,14 @@ func (ctx *TxParseContext) parseTransactionBody(payload []byte, pos, p0 int, slo
|
||||
ctx.ChainID.Sub(&ctx.V, u256.N35)
|
||||
ctx.ChainID.Rsh(&ctx.ChainID, 1)
|
||||
if !ctx.ChainID.Eq(&ctx.cfg.ChainID) {
|
||||
if !ctx.allowPulseChainLegacy {
|
||||
return 0, fmt.Errorf("%w: %s, %d (expected %d)", ErrParseTxn, "invalid chainID", ctx.ChainID.Uint64(), ctx.cfg.ChainID.Uint64())
|
||||
}
|
||||
// If allowPulseChainLegacy, ChainID must be 1 (Ethereum Mainnet).
|
||||
if !ctx.ChainID.Eq(uint256.NewInt(1)) {
|
||||
return 0, fmt.Errorf("%w: %s, %d (expected %d)", ErrParseTxn, "invalid PulseChain chainID", ctx.ChainID.Uint64(), ctx.cfg.ChainID.Uint64())
|
||||
}
|
||||
}
|
||||
|
||||
chainIDBits = ctx.ChainID.BitLen()
|
||||
if chainIDBits <= 7 {
|
||||
|
@ -16,7 +16,7 @@ func FuzzPooledTransactions66(f *testing.F) {
|
||||
f.Add(hexutility.MustDecodeHex("e8bfffffffffffffffffffffffff71e866666666955ef90c91f9fa08f96ebfbfbf007d765059effe33"))
|
||||
f.Fuzz(func(t *testing.T, in []byte) {
|
||||
t.Parallel()
|
||||
ctx := NewTxParseContext(*u256.N1)
|
||||
ctx := NewTxParseContext(*u256.N1, false)
|
||||
slots := TxSlots{}
|
||||
reqId, _, err := ParsePooledTransactions66(in, 0, ctx, &slots, nil)
|
||||
if err != nil {
|
||||
|
@ -143,7 +143,7 @@ func TestPooledTransactionsPacket66(t *testing.T) {
|
||||
encodeBuf = EncodePooledTransactions66(tt.txs, tt.requestID, encodeBuf)
|
||||
require.Equal(tt.encoded, fmt.Sprintf("%x", encodeBuf))
|
||||
|
||||
ctx := NewTxParseContext(*uint256.NewInt(tt.chainID))
|
||||
ctx := NewTxParseContext(*uint256.NewInt(tt.chainID), false)
|
||||
slots := &TxSlots{}
|
||||
requestID, _, err := ParsePooledTransactions66(encodeBuf, 0, ctx, slots, nil)
|
||||
require.NoError(err)
|
||||
@ -162,7 +162,7 @@ func TestPooledTransactionsPacket66(t *testing.T) {
|
||||
require.Equal(tt.encoded, fmt.Sprintf("%x", encodeBuf))
|
||||
|
||||
chainID := uint256.NewInt(tt.chainID)
|
||||
ctx := NewTxParseContext(*chainID)
|
||||
ctx := NewTxParseContext(*chainID, false)
|
||||
slots := &TxSlots{}
|
||||
requestID, _, err := ParsePooledTransactions66(encodeBuf, 0, ctx, slots, func(bytes []byte) error { return ErrRejected })
|
||||
require.NoError(err)
|
||||
@ -203,7 +203,7 @@ func TestTransactionsPacket(t *testing.T) {
|
||||
encodeBuf = EncodeTransactions(tt.txs, encodeBuf)
|
||||
require.Equal(tt.encoded, fmt.Sprintf("%x", encodeBuf))
|
||||
|
||||
ctx := NewTxParseContext(*uint256.NewInt(tt.chainID))
|
||||
ctx := NewTxParseContext(*uint256.NewInt(tt.chainID), false)
|
||||
slots := &TxSlots{}
|
||||
_, err := ParseTransactions(encodeBuf, 0, ctx, slots, nil)
|
||||
require.NoError(err)
|
||||
@ -221,7 +221,7 @@ func TestTransactionsPacket(t *testing.T) {
|
||||
require.Equal(tt.encoded, fmt.Sprintf("%x", encodeBuf))
|
||||
|
||||
chainID := uint256.NewInt(tt.chainID)
|
||||
ctx := NewTxParseContext(*chainID)
|
||||
ctx := NewTxParseContext(*chainID, false)
|
||||
slots := &TxSlots{}
|
||||
_, err := ParseTransactions(encodeBuf, 0, ctx, slots, func(bytes []byte) error { return ErrRejected })
|
||||
require.NoError(err)
|
||||
|
@ -36,7 +36,7 @@ func TestParseTransactionRLP(t *testing.T) {
|
||||
testSet := testSet
|
||||
t.Run(strconv.Itoa(int(testSet.chainID.Uint64())), func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
ctx := NewTxParseContext(testSet.chainID)
|
||||
ctx := NewTxParseContext(testSet.chainID, false)
|
||||
tx, txSender := &TxSlot{}, [20]byte{}
|
||||
for i, tt := range testSet.tests {
|
||||
tt := tt
|
||||
@ -72,7 +72,7 @@ func TestParseTransactionRLP(t *testing.T) {
|
||||
|
||||
func TestTransactionSignatureValidity1(t *testing.T) {
|
||||
chainId := new(uint256.Int).SetUint64(1)
|
||||
ctx := NewTxParseContext(*chainId)
|
||||
ctx := NewTxParseContext(*chainId, false)
|
||||
ctx.WithAllowPreEip2s(true)
|
||||
|
||||
tx, txSender := &TxSlot{}, [20]byte{}
|
||||
@ -96,7 +96,7 @@ func TestTransactionSignatureValidity1(t *testing.T) {
|
||||
// Problematic txn included in a bad block on Görli
|
||||
func TestTransactionSignatureValidity2(t *testing.T) {
|
||||
chainId := new(uint256.Int).SetUint64(5)
|
||||
ctx := NewTxParseContext(*chainId)
|
||||
ctx := NewTxParseContext(*chainId, false)
|
||||
slot, sender := &TxSlot{}, [20]byte{}
|
||||
rlp := hexutility.MustDecodeHex("02f8720513844190ab00848321560082520894cab441d2f45a3fee83d15c6b6b6c36a139f55b6288054607fc96a6000080c001a0dffe4cb5651e663d0eac8c4d002de734dd24db0f1109b062d17da290a133cc02a0913fb9f53f7a792bcd9e4d7cced1b8545d1ab82c77432b0bc2e9384ba6c250c5")
|
||||
_, err := ctx.ParseTransaction(rlp, 0, slot, sender[:], false /* hasEnvelope */, true /* wrappedWithBlobs */, nil)
|
||||
@ -200,7 +200,7 @@ func TestBlobTxParsing(t *testing.T) {
|
||||
bodyEnvelope = append(bodyEnvelope, BlobTxType)
|
||||
bodyEnvelope = append(bodyEnvelope, bodyRlp...)
|
||||
|
||||
ctx := NewTxParseContext(*uint256.NewInt(5))
|
||||
ctx := NewTxParseContext(*uint256.NewInt(5), false)
|
||||
ctx.withSender = false
|
||||
|
||||
var thinTx TxSlot // only tx body, no blobs
|
||||
|
@ -24,7 +24,7 @@ func FuzzParseTx(f *testing.F) {
|
||||
f.Add([]byte{1}, 0)
|
||||
f.Fuzz(func(t *testing.T, in []byte, pos int) {
|
||||
t.Parallel()
|
||||
ctx := NewTxParseContext(*u256.N1)
|
||||
ctx := NewTxParseContext(*u256.N1, false)
|
||||
txn := &TxSlot{}
|
||||
sender := make([]byte, 20)
|
||||
_, _ = ctx.ParseTransaction(in, pos, txn, sender, false /* hasEnvelope */, true /* wrappedWithBlobs */, nil)
|
||||
|
1
go.mod
1
go.mod
@ -88,6 +88,7 @@ require (
|
||||
github.com/valyala/fastjson v1.6.4
|
||||
github.com/vektah/gqlparser/v2 v2.5.10
|
||||
github.com/xsleonard/go-merkle v1.1.0
|
||||
gitlab.com/pulsechaincom/erigon-pulse-snapshot v0.0.2
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/crypto v0.17.0
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
|
||||
|
2
go.sum
2
go.sum
@ -928,6 +928,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
gitlab.com/pulsechaincom/erigon-pulse-snapshot v0.0.2 h1:M/ReqIKALiW5a56bdT8w9j9GZA7yqSEhO9joesRsWBQ=
|
||||
gitlab.com/pulsechaincom/erigon-pulse-snapshot v0.0.2/go.mod h1:U/W4jVFkJQ1XeXul9ng2MFGYRV2bBqTxVjSEojtm18c=
|
||||
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
|
@ -262,7 +262,10 @@ func makeP2PServer(
|
||||
protocols []p2p.Protocol,
|
||||
) (*p2p.Server, error) {
|
||||
var urls []string
|
||||
chainConfig := params.ChainConfigByGenesisHash(genesisHash)
|
||||
chainConfig := params.ChainConfigByChainName(p2pConfig.ChainName)
|
||||
if chainConfig == nil {
|
||||
chainConfig = params.ChainConfigByGenesisHash(genesisHash)
|
||||
}
|
||||
if chainConfig != nil {
|
||||
urls = params.BootnodeURLsOfChain(chainConfig.ChainName)
|
||||
}
|
||||
@ -990,7 +993,7 @@ func (ss *GrpcServer) SetStatus(ctx context.Context, statusData *proto_sentry.St
|
||||
var err error
|
||||
if !ss.p2p.NoDiscovery {
|
||||
if len(ss.discoveryDNS) == 0 {
|
||||
if url := params.KnownDNSNetwork(genesisHash, "all"); url != "" {
|
||||
if url := params.KnownDNSNetwork(genesisHash, statusData.NetworkId, "all"); url != "" {
|
||||
ss.discoveryDNS = []string{url}
|
||||
}
|
||||
}
|
||||
|
@ -173,6 +173,9 @@ type Config struct {
|
||||
// whenever a message is sent to or received from a peer
|
||||
EnableMsgEvents bool
|
||||
|
||||
// ChainName is the name of the chain config
|
||||
ChainName string `toml:",omitempty"`
|
||||
|
||||
// it is actually used but a linter got confused
|
||||
clock mclock.Clock //nolint:structcheck
|
||||
|
||||
|
@ -146,16 +146,42 @@ var ChiadoBootnodes = []string{
|
||||
"enode://595160631241ea41b187b85716f9f9572a266daa940d74edbe3b83477264ce284d69208e61cf50e91641b1b4f9a03fa8e60eb73d435a84cf4616b1c969bc2512@3.69.35.13:30303",
|
||||
}
|
||||
|
||||
const dnsPrefix = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@"
|
||||
// PulsechainBootnodes are the enode URLs of the P2P bootstrap nodes running on
|
||||
// the main Pulsechain network.
|
||||
var PulsechainBootnodes = []string{
|
||||
// Pulsechain Go Bootnodes
|
||||
}
|
||||
|
||||
// PulsechainTestnetBootnodes are the enode URLs of the P2P bootstrap nodes running on
|
||||
// the Pulsechain testnet network.
|
||||
var PulsechainTestnetBootnodes = []string{
|
||||
// Pulsechain Go Bootnodes
|
||||
}
|
||||
|
||||
// KnownDNSNetwork returns the address of a public DNS-based node list for the given
|
||||
// genesis hash and protocol. See https://github.com/ethereum/discv4-dns-lists for more
|
||||
// information.
|
||||
func KnownDNSNetwork(genesis libcommon.Hash, protocol string) string {
|
||||
func KnownDNSNetwork(genesis libcommon.Hash, networkID uint64, protocol string) string {
|
||||
var net string
|
||||
var dnsPrefix = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@"
|
||||
var tld = ".ethdisco.net"
|
||||
|
||||
if networkID == NetworkIDByChainName(networkname.PulsechainChainName) || networkID == NetworkIDByChainName(networkname.PulsechainTestnetChainName) {
|
||||
tld = ".pulsedisco.net"
|
||||
dnsPrefix = "enrtree://APFXO36RU3TWV7XFGWI2TYF5IDA3WM2GPTRL3TCZINWHZX4R6TAOK@"
|
||||
}
|
||||
|
||||
switch genesis {
|
||||
case MainnetGenesisHash:
|
||||
switch networkID {
|
||||
case NetworkIDByChainName(networkname.PulsechainChainName):
|
||||
net = "PulseChain"
|
||||
case NetworkIDByChainName(networkname.PulsechainTestnetChainName):
|
||||
// TODO(bretep): Change to PulseChainTestnetV3
|
||||
net = "PulseChainTestnet"
|
||||
default:
|
||||
net = "mainnet"
|
||||
}
|
||||
case GoerliGenesisHash:
|
||||
net = "goerli"
|
||||
case SepoliaGenesisHash:
|
||||
@ -163,7 +189,7 @@ func KnownDNSNetwork(genesis libcommon.Hash, protocol string) string {
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
return dnsPrefix + protocol + "." + net + ".ethdisco.net"
|
||||
return dnsPrefix + protocol + "." + net + tld
|
||||
}
|
||||
|
||||
func BootnodeURLsOfChain(chain string) []string {
|
||||
@ -186,6 +212,10 @@ func BootnodeURLsOfChain(chain string) []string {
|
||||
return GnosisBootnodes
|
||||
case networkname.ChiadoChainName:
|
||||
return ChiadoBootnodes
|
||||
case networkname.PulsechainChainName:
|
||||
return PulsechainBootnodes
|
||||
case networkname.PulsechainTestnetChainName:
|
||||
return PulsechainTestnetBootnodes
|
||||
default:
|
||||
return []string{}
|
||||
}
|
||||
|
29
params/chainspecs/pulsechain-testnet.json
Normal file
29
params/chainspecs/pulsechain-testnet.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"ChainName": "pulsechain-testnet",
|
||||
"chainId": 942,
|
||||
"homesteadBlock": 1150000,
|
||||
"daoForkBlock": 1920000,
|
||||
"daoForkSupport": true,
|
||||
"eip150Block": 2463000,
|
||||
"eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0",
|
||||
"eip155Block": 2675000,
|
||||
"byzantiumBlock": 4370000,
|
||||
"constantinopleBlock": 7280000,
|
||||
"petersburgBlock": 7280000,
|
||||
"istanbulBlock": 9069000,
|
||||
"muirGlacierBlock": 9200000,
|
||||
"berlinBlock": 12244000,
|
||||
"londonBlock": 12965000,
|
||||
"arrowGlacierBlock": 13773000,
|
||||
"grayGlacierBlock": 15050000,
|
||||
"terminalTotalDifficulty": 58750003716598352947541,
|
||||
"terminalTotalDifficultyPassed": true,
|
||||
"ethash": {},
|
||||
"primordialPulseBlock": 15669697,
|
||||
"pulseChain": {
|
||||
"treasury": {
|
||||
"addr": "0xceB59257450820132aB274ED61C49E5FD96E8868",
|
||||
"balance": "0xc9f2c9cd04674edea40000000"
|
||||
}
|
||||
}
|
||||
}
|
24
params/chainspecs/pulsechain.json
Normal file
24
params/chainspecs/pulsechain.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"ChainName": "pulsechain",
|
||||
"chainId": 369,
|
||||
"homesteadBlock": 1150000,
|
||||
"daoForkBlock": 1920000,
|
||||
"daoForkSupport": true,
|
||||
"eip150Block": 2463000,
|
||||
"eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0",
|
||||
"eip155Block": 2675000,
|
||||
"byzantiumBlock": 4370000,
|
||||
"constantinopleBlock": 7280000,
|
||||
"petersburgBlock": 7280000,
|
||||
"istanbulBlock": 9069000,
|
||||
"muirGlacierBlock": 9200000,
|
||||
"berlinBlock": 12244000,
|
||||
"londonBlock": 12965000,
|
||||
"arrowGlacierBlock": 13773000,
|
||||
"grayGlacierBlock": 15050000,
|
||||
"terminalTotalDifficulty": 58750003716598352947541,
|
||||
"terminalTotalDifficultyPassed": true,
|
||||
"ethash": {},
|
||||
"primordialPulseBlock": 15669697,
|
||||
"pulseChain": {}
|
||||
}
|
@ -72,6 +72,8 @@ var (
|
||||
BorDevnetGenesisHash = libcommon.HexToHash("0x5a06b25b0c6530708ea0b98a3409290e39dce6be7f558493aeb6e4b99a172a87")
|
||||
GnosisGenesisHash = libcommon.HexToHash("0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756")
|
||||
ChiadoGenesisHash = libcommon.HexToHash("0xada44fd8d2ecab8b08f256af07ad3e777f17fb434f8f8e678b312f576212ba9a")
|
||||
PulsechainGenesisHash = libcommon.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
|
||||
PulsechainTetnetGenesisHash = libcommon.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
|
||||
)
|
||||
|
||||
var (
|
||||
@ -114,6 +116,8 @@ var (
|
||||
ShanghaiTime: big.NewInt(0),
|
||||
CancunTime: big.NewInt(0),
|
||||
Ethash: new(chain.EthashConfig),
|
||||
PrimordialPulseBlock: nil,
|
||||
PulseChain: nil,
|
||||
}
|
||||
|
||||
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
||||
@ -146,6 +150,10 @@ var (
|
||||
|
||||
ChiadoChainConfig = readChainSpec("chainspecs/chiado.json")
|
||||
|
||||
PulsechainChainConfig = readChainSpec("chainspecs/pulsechain.json")
|
||||
|
||||
PulsechainTestnetChainConfig = readChainSpec("chainspecs/pulsechain-testnet.json")
|
||||
|
||||
CliqueSnapshot = NewSnapshotConfig(10, 1024, 16384, true, "")
|
||||
|
||||
TestChainConfig = &chain.Config{
|
||||
@ -161,6 +169,8 @@ var (
|
||||
MuirGlacierBlock: big.NewInt(0),
|
||||
BerlinBlock: big.NewInt(0),
|
||||
Ethash: new(chain.EthashConfig),
|
||||
PrimordialPulseBlock: nil,
|
||||
PulseChain: nil,
|
||||
}
|
||||
|
||||
TestChainAuraConfig = &chain.Config{
|
||||
@ -230,6 +240,10 @@ func ChainConfigByChainName(chain string) *chain.Config {
|
||||
return GnosisChainConfig
|
||||
case networkname.ChiadoChainName:
|
||||
return ChiadoChainConfig
|
||||
case networkname.PulsechainChainName:
|
||||
return PulsechainChainConfig
|
||||
case networkname.PulsechainTestnetChainName:
|
||||
return PulsechainTestnetChainConfig
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@ -257,6 +271,10 @@ func GenesisHashByChainName(chain string) *libcommon.Hash {
|
||||
return &GnosisGenesisHash
|
||||
case networkname.ChiadoChainName:
|
||||
return &ChiadoGenesisHash
|
||||
case networkname.PulsechainChainName:
|
||||
return &PulsechainGenesisHash
|
||||
case networkname.PulsechainTestnetChainName:
|
||||
return &PulsechainTetnetGenesisHash
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
78
pulse/deposit_contract.go
Normal file
78
pulse/deposit_contract.go
Normal file
File diff suppressed because one or more lines are too long
13
pulse/pulse.go
Normal file
13
pulse/pulse.go
Normal file
@ -0,0 +1,13 @@
|
||||
// Package pulse implements the PulseChain fork.
|
||||
package pulse
|
||||
|
||||
import (
|
||||
"github.com/ledgerwatch/erigon-lib/chain"
|
||||
"github.com/ledgerwatch/erigon/core/state"
|
||||
)
|
||||
|
||||
// PrimordialPulseFork applies the PrimordialPulse fork changes.
|
||||
func PrimordialPulseFork(state *state.IntraBlockState, pulseChainConfig *chain.PulseChainConfig) {
|
||||
applySacrificeCredits(state, pulseChainConfig)
|
||||
replaceDepositContract(state)
|
||||
}
|
BIN
pulse/sacrifice_credits.bin
Normal file
BIN
pulse/sacrifice_credits.bin
Normal file
Binary file not shown.
56
pulse/sacrifice_credits.go
Normal file
56
pulse/sacrifice_credits.go
Normal file
@ -0,0 +1,56 @@
|
||||
package pulse
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/ledgerwatch/erigon-lib/chain"
|
||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||
"github.com/ledgerwatch/log/v3"
|
||||
|
||||
"github.com/ledgerwatch/erigon/core/state"
|
||||
)
|
||||
|
||||
// The testnet credits are approximate and not final for mainnet
|
||||
// see https://gitlab.com/pulsechaincom/compressed-allocations/-/tree/Testnet-R2-Credits
|
||||
//
|
||||
//go:embed sacrifice_credits.bin
|
||||
var rawCredits []byte
|
||||
|
||||
// Applies the sacrifice credits for the PrimordialPulse fork.
|
||||
func applySacrificeCredits(state *state.IntraBlockState, pulseChainConfig *chain.PulseChainConfig) {
|
||||
if pulseChainConfig != nil && pulseChainConfig.Treasury != nil {
|
||||
balance, err := uint256.FromHex(pulseChainConfig.Treasury.Balance)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Info("Applying PrimordialPulse treasury allocation 💸")
|
||||
log.Info(fmt.Sprintf("Applying PrimordialPulse treasury allocation address: %s", libcommon.HexToAddress(pulseChainConfig.Treasury.Addr).String()))
|
||||
log.Info(fmt.Sprintf("Applying PrimordialPulse treasury allocation amount: %d", balance))
|
||||
state.AddBalance(libcommon.HexToAddress(pulseChainConfig.Treasury.Addr), balance)
|
||||
}
|
||||
|
||||
log.Info("Applying PrimordialPulse sacrifice credits 💸")
|
||||
for ptr := 0; ptr < len(rawCredits); {
|
||||
byteCount := int(rawCredits[ptr])
|
||||
ptr++
|
||||
|
||||
record := rawCredits[ptr : ptr+byteCount]
|
||||
ptr += byteCount
|
||||
|
||||
addr := libcommon.BytesToAddress(record[:20])
|
||||
hexBalance := hex.EncodeToString(record[20:])
|
||||
credit, err := uint256.FromHex("0x" + strings.TrimLeft(hexBalance, "0"))
|
||||
if err != nil {
|
||||
log.Info(fmt.Sprintf("Applying PrimordialPulse sacrifice credits amount: %s", hexBalance))
|
||||
panic(err)
|
||||
}
|
||||
state.AddBalance(addr, credit)
|
||||
|
||||
}
|
||||
|
||||
log.Info("Finished applying PrimordialPulse sacrifice credits 🤑")
|
||||
}
|
@ -84,6 +84,10 @@ func NewNodConfigUrfave(ctx *cli.Context, logger log.Logger) *nodecfg.Config {
|
||||
logger.Info("Starting Erigon on Bor Mainnet...")
|
||||
case networkname.BorDevnetChainName:
|
||||
logger.Info("Starting Erigon on Bor Devnet...")
|
||||
case networkname.PulsechainChainName:
|
||||
logger.Info("Starting Erigon on PulseChain...")
|
||||
case networkname.PulsechainTestnetChainName:
|
||||
logger.Info("Starting Erigon on PulseChain Testnet...")
|
||||
case "", networkname.MainnetChainName:
|
||||
if !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
||||
logger.Info("Starting Erigon on Ethereum mainnet...")
|
||||
|
@ -1796,6 +1796,7 @@ func DumpTxs(ctx context.Context, db kv.RoDB, blockFrom, blockTo uint64, chainCo
|
||||
defer cancel()
|
||||
|
||||
chainID, _ := uint256.FromBig(chainConfig.ChainID)
|
||||
isPulseChain := chainConfig.PulseChain != nil
|
||||
|
||||
numBuf := make([]byte, 8)
|
||||
|
||||
@ -1904,7 +1905,7 @@ func DumpTxs(ctx context.Context, db kv.RoDB, blockFrom, blockTo uint64, chainCo
|
||||
valueBuf := bufPool.Get().([]byte)
|
||||
defer bufPool.Put(valueBuf) //nolint
|
||||
valueBufs[i] = valueBuf
|
||||
parseCtxs[i] = types2.NewTxParseContext(*chainID)
|
||||
parseCtxs[i] = types2.NewTxParseContext(*chainID, isPulseChain)
|
||||
}
|
||||
|
||||
if err := addSystemTx(parseCtxs[0], tx, body.BaseTxId); err != nil {
|
||||
@ -2205,8 +2206,8 @@ func TransactionsIdx(ctx context.Context, chainConfig *chain.Config, version uin
|
||||
txnHash2BlockNumIdx.LogLvl(log.LvlDebug)
|
||||
|
||||
chainId, _ := uint256.FromBig(chainConfig.ChainID)
|
||||
|
||||
parseCtx := types2.NewTxParseContext(*chainId)
|
||||
isPulseChain := chainConfig.PulseChain != nil
|
||||
parseCtx := types2.NewTxParseContext(*chainId, isPulseChain)
|
||||
parseCtx.WithSender(false)
|
||||
slot := types2.TxSlot{}
|
||||
bodyBuf, word := make([]byte, 0, 4096), make([]byte, 0, 4096)
|
||||
|
@ -101,7 +101,7 @@ func TestDump(t *testing.T) {
|
||||
t.Run("txs", func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
slot := types2.TxSlot{}
|
||||
parseCtx := types2.NewTxParseContext(*chainID)
|
||||
parseCtx := types2.NewTxParseContext(*chainID, false)
|
||||
parseCtx.WithSender(false)
|
||||
var sender [20]byte
|
||||
|
||||
@ -126,7 +126,7 @@ func TestDump(t *testing.T) {
|
||||
t.Run("txs_not_from_zero", func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
slot := types2.TxSlot{}
|
||||
parseCtx := types2.NewTxParseContext(*chainID)
|
||||
parseCtx := types2.NewTxParseContext(*chainID, false)
|
||||
parseCtx.WithSender(false)
|
||||
var sender [20]byte
|
||||
|
||||
|
@ -609,7 +609,7 @@ func (hd *HeaderDownload) InsertHeader(hf FeedHeaderFunc, terminalTotalDifficult
|
||||
link.ClearChildren()
|
||||
}
|
||||
var blocksToTTD uint64
|
||||
if terminalTotalDifficulty != nil && returnTd != nil && lastD != nil {
|
||||
if terminalTotalDifficulty != nil && returnTd != nil && lastD != nil && lastD.Uint64() != 0 {
|
||||
// Calculate the estimation of when TTD will be hit
|
||||
var x big.Int
|
||||
x.Sub(terminalTotalDifficulty, returnTd)
|
||||
|
Loading…
Reference in New Issue
Block a user