diff --git a/cmd/geth/main.go b/cmd/geth/main.go index b9e3ed31e813..61e6e07e30d4 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -290,6 +290,9 @@ func prepare(ctx *cli.Context) { case ctx.IsSet(utils.KilnFlag.Name): log.Info("Starting Geth on Kiln testnet...") + case ctx.IsSet(utils.WbtTestnetFlag.Name): + log.Info("Starting Geth on WhiteBIT test network...") + case ctx.IsSet(utils.DeveloperFlag.Name): log.Info("Starting Geth in ephemeral dev mode...") log.Warn(`You are running Geth in --dev mode. Please note the following: @@ -319,6 +322,7 @@ func prepare(ctx *cli.Context) { !ctx.IsSet(utils.RinkebyFlag.Name) && !ctx.IsSet(utils.GoerliFlag.Name) && !ctx.IsSet(utils.KilnFlag.Name) && + !ctx.IsSet(utils.WbtTestnetFlag.Name) && !ctx.IsSet(utils.DeveloperFlag.Name) { // Nope, we're really on mainnet. Bump that cache up! log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 9e95193343a9..ee6494ca319e 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -153,6 +153,11 @@ var ( Usage: "Kiln network: pre-configured proof-of-work to proof-of-stake test network", Category: flags.EthCategory, } + WbtTestnetFlag = &cli.BoolFlag{ + Name: "wbt-testnet", + Usage: "WhiteBIT test network", + Category: flags.EthCategory, + } // Dev mode DeveloperFlag = &cli.BoolFlag{ @@ -987,6 +992,7 @@ var ( GoerliFlag, SepoliaFlag, KilnFlag, + WbtTestnetFlag, } // NetworkFlags is the flag group of all built-in supported networks. NetworkFlags = append([]cli.Flag{ @@ -1079,6 +1085,8 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { urls = params.GoerliBootnodes case ctx.Bool(KilnFlag.Name): urls = params.KilnBootnodes + case ctx.Bool(WbtTestnetFlag.Name): + urls = params.WbtTestnetBootnodes } // don't apply defaults if BootstrapNodes is already set @@ -1727,7 +1735,7 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) { // SetEthConfig applies eth-related command line flags to the config. func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { // Avoid conflicting network flags - CheckExclusive(ctx, MainnetFlag, DeveloperFlag, RopstenFlag, RinkebyFlag, GoerliFlag, SepoliaFlag, KilnFlag) + CheckExclusive(ctx, MainnetFlag, DeveloperFlag, RopstenFlag, RinkebyFlag, GoerliFlag, SepoliaFlag, KilnFlag, WbtTestnetFlag) CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light") CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer if ctx.String(GCModeFlag.Name) == "archive" && ctx.Uint64(TxLookupLimitFlag.Name) != 0 { @@ -1908,6 +1916,11 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } cfg.Genesis = core.DefaultKilnGenesisBlock() SetDNSDiscoveryDefaults(cfg, params.KilnGenesisHash) + case ctx.Bool(WbtTestnetFlag.Name): + if !ctx.IsSet(NetworkIdFlag.Name) { + cfg.NetworkId = 2625 + } + cfg.Genesis = core.DefaultWbtTestnetGenesisBlock() case ctx.Bool(DeveloperFlag.Name): if !ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkId = 1337 @@ -2159,6 +2172,8 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis { genesis = core.DefaultGoerliGenesisBlock() case ctx.Bool(KilnFlag.Name): genesis = core.DefaultKilnGenesisBlock() + case ctx.Bool(WbtTestnetFlag.Name): + genesis = core.DefaultWbtTestnetGenesisBlock() case ctx.Bool(DeveloperFlag.Name): Fatalf("Developer chains are ephemeral") } diff --git a/core/genesis.go b/core/genesis.go index c3b5d0b57094..98c29f8d7489 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -160,6 +160,8 @@ func CommitGenesisState(db ethdb.Database, hash common.Hash) error { genesis = DefaultGoerliGenesisBlock() case params.SepoliaGenesisHash: genesis = DefaultSepoliaGenesisBlock() + case params.WbtTestnetGenesisHash: + genesis = DefaultWbtTestnetGenesisBlock() } if genesis != nil { alloc = genesis.Alloc @@ -357,6 +359,8 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { return params.GoerliChainConfig case ghash == params.KilnGenesisHash: return DefaultKilnGenesisBlock().Config + case ghash == params.WbtTestnetGenesisHash: + return params.WbtTestnetChainConfig default: return params.AllEthashProtocolChanges } @@ -513,6 +517,22 @@ func DefaultKilnGenesisBlock() *Genesis { return g } +// DefaultWbtTestnetGenesisBlock returns the WhiteBIT test network genesis block. +func DefaultWbtTestnetGenesisBlock() *Genesis { + return &Genesis{ + Config: params.WbtTestnetChainConfig, + Timestamp: 1680259313, + ExtraData: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000003d00c266f957fa411a3855c322f11cbf21bebb2f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + GasLimit: 4700000, + Difficulty: big.NewInt(1), + Alloc: GenesisAlloc{ + common.HexToAddress("0x55064C96A455370a21c7eC3Ac3112B562be9f70F"): GenesisAccount{ + Balance: new(big.Int).Mul(big.NewInt(400000000000), big.NewInt(params.Ether)), + }, + }, + } +} + // DeveloperGenesisBlock returns the 'geth --dev' genesis block. func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *Genesis { // Override the default period to the user requested one diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index b159f34e64ba..b2d7fe938893 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -639,7 +639,9 @@ func (api *ConsensusAPI) heartbeat() { } // Estimate an ETA based on the block times and the difficulty growth growth := diff / float64(head.Time()-block.Time()+1) // +1 to avoid div by zero - if growth > 0 { + // `growth` value can be less than 1 so division by zero error can happen + // This code may not be executed after the merge, but it can crash application before the merge happens + if int64(growth) > 0 { if left := new(big.Int).Sub(ttd, htd); left.IsUint64() { eta = time.Duration(float64(left.Uint64())/growth) * time.Second } else { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index e6740942d859..21c03acd5e6e 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1573,6 +1573,75 @@ func (s *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash commo return tx.MarshalBinary() } +func (s *TransactionAPI) GetBlockReceipts(ctx context.Context, blockHash common.Hash) ([]map[string]interface{}, error) { + block, err := s.b.BlockByHash(ctx, blockHash) + if err != nil { + return nil, err + } + + receipts, err := s.b.GetReceipts(ctx, blockHash) + if err != nil { + return nil, err + } + + if len(receipts) != len(block.Transactions()) { + return nil, errors.New("receipts and transactions count mismatch") + } + + output := make([]map[string]interface{}, len(receipts)) + + for index, receipt := range receipts { + tx := block.Transactions()[index] + + // Derive the sender. + signer := types.MakeSigner(s.b.ChainConfig(), block.Number()) + from, _ := types.Sender(signer, tx) + + fields := map[string]interface{}{ + "blockHash": blockHash, + "blockNumber": hexutil.Uint64(block.NumberU64()), + "transactionHash": tx.Hash(), + "transactionIndex": hexutil.Uint64(index), + "from": from, + "to": tx.To(), + "gasUsed": hexutil.Uint64(receipt.GasUsed), + "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed), + "contractAddress": nil, + "logs": receipt.Logs, + "logsBloom": receipt.Bloom, + "type": hexutil.Uint(tx.Type()), + } + // Assign the effective gas price paid + if !s.b.ChainConfig().IsLondon(block.Number()) { + fields["effectiveGasPrice"] = hexutil.Uint64(tx.GasPrice().Uint64()) + } else { + header, err := s.b.HeaderByHash(ctx, blockHash) + if err != nil { + return nil, err + } + gasPrice := new(big.Int).Add(header.BaseFee, tx.EffectiveGasTipValue(header.BaseFee)) + fields["effectiveGasPrice"] = hexutil.Uint64(gasPrice.Uint64()) + } + // Assign receipt status or post state. + if len(receipt.PostState) > 0 { + fields["root"] = hexutil.Bytes(receipt.PostState) + } else { + fields["status"] = hexutil.Uint(receipt.Status) + } + if receipt.Logs == nil { + fields["logs"] = []*types.Log{} + } + // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation + if receipt.ContractAddress != (common.Address{}) { + fields["contractAddress"] = receipt.ContractAddress + } + + output[index] = fields + } + + return output, nil +} + // GetTransactionReceipt returns the transaction receipt for the given transaction hash. func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) { tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash) diff --git a/params/bootnodes.go b/params/bootnodes.go index b80997774536..e871f221de74 100644 --- a/params/bootnodes.go +++ b/params/bootnodes.go @@ -82,6 +82,12 @@ var KilnBootnodes = []string{ "enode://b74bd2e8a9f0c53f0c93bcce80818f2f19439fd807af5c7fbc3efb10130c6ee08be8f3aaec7dc0a057ad7b2a809c8f34dc62431e9b6954b07a6548cc59867884@164.92.140.200:30303", } +var WbtTestnetBootnodes = []string{ + "enode://5da705c3da6701cade478c078c6c655a1996127d6141c9ced4cd7dd0f01a999333db0ca7efe322d0ea5cec94d8dd8fd2064035cc1e7b59d843ca156fa2280626@bootnode1-testnet.whitebit.network:30303", + "enode://15dd558bda09365ae0e86ab980c7192e50b91b07f308ece9d3ca1bd00ca7f0ff9a4f96f0ca0affb686e8453e4209e58cdc1c6504da2750f7766348121dad2f14@bootnode2-testnet.whitebit.network:30303", + "enode://7c0560592ae6e7275b78df611191338731c839b992d16d209fcdda473d2310cd5b9596b5a03a0b34e3788a02ba29622c09500ee2a7c4629e6fd3e19d35da6472@bootnode3-testnet.whitebit.network:30303", +} + var V5Bootnodes = []string{ // Teku team's bootnode "enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA", diff --git a/params/config.go b/params/config.go index 80e671f9bf41..f0e96f459605 100644 --- a/params/config.go +++ b/params/config.go @@ -27,12 +27,13 @@ import ( // Genesis hashes to enforce below configs on. var ( - MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") - RopstenGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") - SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9") - RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") - GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") - KilnGenesisHash = common.HexToHash("0x51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8") + MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") + RopstenGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") + SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9") + RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") + GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") + KilnGenesisHash = common.HexToHash("0x51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8") + WbtTestnetGenesisHash = common.HexToHash("0x3786ce655da7e41d4164e255422df800c7276d94b0c4b10f856ae67ab48119c4") ) // TrustedCheckpoints associates each known checkpoint with the genesis hash of @@ -265,6 +266,31 @@ var ( Threshold: 2, } + // WbtTestnetChainConfig contains config for the WhiteBIT test network + WbtTestnetChainConfig = &ChainConfig{ + ChainID: big.NewInt(2625), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: false, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: nil, + BerlinBlock: nil, + LondonBlock: nil, + ArrowGlacierBlock: nil, + TerminalTotalDifficulty: nil, + TerminalTotalDifficultyPassed: false, + Clique: &CliqueConfig{ + Period: 2, + Epoch: 30000, + }, + } + // AllEthashProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Ethash consensus. // @@ -285,11 +311,12 @@ var ( // NetworkNames are user friendly names to use in the chain spec banner. var NetworkNames = map[string]string{ - MainnetChainConfig.ChainID.String(): "mainnet", - RopstenChainConfig.ChainID.String(): "ropsten", - RinkebyChainConfig.ChainID.String(): "rinkeby", - GoerliChainConfig.ChainID.String(): "goerli", - SepoliaChainConfig.ChainID.String(): "sepolia", + MainnetChainConfig.ChainID.String(): "mainnet", + RopstenChainConfig.ChainID.String(): "ropsten", + RinkebyChainConfig.ChainID.String(): "rinkeby", + GoerliChainConfig.ChainID.String(): "goerli", + SepoliaChainConfig.ChainID.String(): "sepolia", + WbtTestnetChainConfig.ChainID.String(): "wbt-testnet", } // TrustedCheckpoint represents a set of post-processed trie roots (CHT and diff --git a/params/version.go b/params/version.go index d9a3958512c3..a89668f3b5a1 100644 --- a/params/version.go +++ b/params/version.go @@ -21,9 +21,9 @@ import ( ) const ( - VersionMajor = 1 // Major version component of the current release - VersionMinor = 10 // Minor version component of the current release - VersionPatch = 26 // Patch version component of the current release + VersionMajor = 0 // Major version component of the current release + VersionMinor = 1 // Minor version component of the current release + VersionPatch = 0 // Patch version component of the current release VersionMeta = "stable" // Version metadata to append to the version string )