When starting up, the Geth client begins by parsing the command line parameters. This process kicks off with the geth
function: func geth(ctx *cli.Context) error
at cmd/geth/main.go:326
where the geth
prepares the metric if enabled. Subsequently, the makeFullNode
function takes over. It reads the provided configuration file or command line flags. As a result, it returns two key components: the protocol stack and the backend API.
启动时,Geth 客户端首先解析命令行参数。此过程从以下 geth
函数开始: func geth(ctx *cli.Context) error
如果 cmd/geth/main.go:326
启用,则 geth
在准备指标的位置。随后,该功能 makeFullNode
接管。它读取提供的配置文件或命令行标志。因此,它返回两个关键组件:协议栈和后端 API。
It’s worth noting the importance of the Backend API. It establishes a myriad of interfaces, facilitating interaction with nodes and handling external RPC call limits.
值得注意的是后端 API 的重要性。它建立了无数的接口,促进了与节点的交互并处理外部 RPC 调用限制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
// Backend interface provides the common API services (that are provided by // both full and light clients) with access to necessary functions. type Backend interface { // General Ethereum API SyncProgress() ethereum.SyncProgress SuggestGasTipCap(ctx context.Context) (*big.Int, error) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) ChainDb() ethdb.Database AccountManager() *accounts.Manager ExtRPCEnabled() bool RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection RPCEVMTimeout() time.Duration // global timeout for eth_call over rpc: DoS protection RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs UnprotectedAllowed() bool // allows only for EIP155 transactions. // Blockchain API SetHead(number uint64) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) CurrentHeader() *types.Header CurrentBlock() *types.Header BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) PendingBlockAndReceipts() (*types.Block, types.Receipts) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) GetTd(ctx context.Context, hash common.Hash) *big.Int GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription // Transaction pool API SendTx(ctx context.Context, signedTx *types.Transaction) error GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) GetPoolTransactions() (types.Transactions, error) GetPoolTransaction(txHash common.Hash) *types.Transaction GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) Stats() (pending int, queued int) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription ChainConfig() *params.ChainConfig Engine() consensus.Engine // This is copied from filters.Backend // eth/filters needs to be initialized from this backend type, so methods needed by // it must also be included here. GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription BloomStatus() (uint64, uint64) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) } |
For instance, the SyncProgress()
method captures the node’s status as it synchronizes with the Ethereum network.
例如,该方法 SyncProgress()
在与以太坊网络同步时捕获节点的状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
type SyncProgress struct { StartingBlock uint64 // Block number where sync began CurrentBlock uint64 // Current block number where sync is at HighestBlock uint64 // Highest alleged block number in the chain // "fast sync" fields. These used to be sent by geth, but are no longer used // since version v1.10. PulledStates uint64 // Number of state trie entries already downloaded KnownStates uint64 // Total number of state trie entries known about // "snap sync" fields. SyncedAccounts uint64 // Number of accounts downloaded SyncedAccountBytes uint64 // Number of account trie bytes persisted to disk SyncedBytecodes uint64 // Number of bytecodes downloaded SyncedBytecodeBytes uint64 // Number of bytecode bytes downloaded SyncedStorage uint64 // Number of storage slots downloaded SyncedStorageBytes uint64 // Number of storage trie bytes persisted to disk HealedTrienodes uint64 // Number of state trie nodes downloaded HealedTrienodeBytes uint64 // Number of state trie bytes persisted to disk HealedBytecodes uint64 // Number of bytecodes downloaded HealedBytecodeBytes uint64 // Number of bytecodes persisted to disk HealingTrienodes uint64 // Number of state trie nodes pending HealingBytecode uint64 // Number of bytecodes pending } |
Regarding the protocol stack, it’s represented by the Node
structure, which comprises numerous fields. Among these, the stop
field plays a pivotal role as it signals the termination of the server.
关于协议栈,它由结构表示,该 Node
结构包含许多字段。其中,该 stop
字段起着关键作用,因为它发出服务器终止的信号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Node is a container on which services can be registered. type Node struct { eventmux *event.TypeMux config *Config accman *accounts.Manager log log.Logger keyDir string // key store directory keyDirTemp bool // If true, key directory will be removed by Stop dirLock *flock.Flock // prevents concurrent use of instance directory stop chan struct{} // Channel to wait for termination notifications server *p2p.Server // Currently running P2P networking layer startStopLock sync.Mutex // Start/Stop are protected by an additional lock state int // Tracks state of node lifecycle lock sync.Mutex lifecycles []Lifecycle // All registered backends, services, and auxiliary services that have a lifecycle rpcAPIs []rpc.API // List of APIs currently provided by the node http *httpServer // ws *httpServer // httpAuth *httpServer // wsAuth *httpServer // ipc *ipcServer // Stores information about the ipc http server inprocHandler *rpc.Server // In-process RPC request handler to process the API requests databases map[*closeTrackingDB]struct{} // All open databases } |
Once all configurations are in place and prior to the server’s actual launch, you should observe the following output:
一旦所有配置都到位,在服务器实际启动之前,您应该观察到以下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
INFO [09-13|12:46:39.391] Starting Geth on Ethereum mainnet... INFO [09-13|12:46:39.392] Bumping default cache on mainnet provided=1024 updated=4096 INFO [09-13|12:46:39.396] Maximum peer count ETH=50 LES=0 total=50 INFO [09-13|12:46:39.400] Smartcard socket not found, disabling err="stat /run/pcscd/pcscd.comm: no such file or directory" INFO [09-13|12:46:39.408] Set global gas cap cap=50,000,000 INFO [09-13|12:46:39.408] Initializing the KZG library backend=gokzg INFO [09-13|12:46:39.611] Allocated trie memory caches clean=614.00MiB dirty=1024.00MiB INFO [09-13|12:46:39.611] Using pebble as the backing database INFO [09-13|12:46:39.611] Allocated cache and file handles database=/home/username/.ethereum/geth/chaindata cache=2.00GiB handles=32767 INFO [09-13|12:46:39.677] Opened ancient database database=/home/username/.ethereum/geth/chaindata/ancient/chain readonly=false INFO [09-13|12:46:39.681] Initialising Ethereum protocol network=1 dbversion=8 INFO [09-13|12:46:39.681] INFO [09-13|12:46:39.681] --------------------------------------------------------------------------------------------------------------------------------------------------------- INFO [09-13|12:46:39.683] Chain ID: 1 (mainnet) INFO [09-13|12:46:39.683] Consensus: Beacon (proof-of-stake), merged from Ethash (proof-of-work) INFO [09-13|12:46:39.683] INFO [09-13|12:46:39.683] Pre-Merge hard forks (block based): INFO [09-13|12:46:39.683] - Homestead: #1150000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md) INFO [09-13|12:46:39.683] - DAO Fork: #1920000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md) INFO [09-13|12:46:39.683] - Tangerine Whistle (EIP 150): #2463000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md) INFO [09-13|12:46:39.683] - Spurious Dragon/1 (EIP 155): #2675000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md) INFO [09-13|12:46:39.683] - Spurious Dragon/2 (EIP 158): #2675000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md) INFO [09-13|12:46:39.683] - Byzantium: #4370000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md) INFO [09-13|12:46:39.683] - Constantinople: #7280000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md) INFO [09-13|12:46:39.683] - Petersburg: #7280000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md) INFO [09-13|12:46:39.683] - Istanbul: #9069000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md) INFO [09-13|12:46:39.683] - Muir Glacier: #9200000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md) INFO [09-13|12:46:39.683] - Berlin: #12244000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md) INFO [09-13|12:46:39.683] - London: #12965000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md) INFO [09-13|12:46:39.683] - Arrow Glacier: #13773000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md) INFO [09-13|12:46:39.683] - Gray Glacier: #15050000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md) INFO [09-13|12:46:39.683] INFO [09-13|12:46:39.683] Merge configurationd: INFO [09-13|12:46:39.683] - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md INFO [09-13|12:46:39.683] - Network known to be merged: true INFO [09-13|12:46:39.683] - Total terminal difficulty: 58750000000000000000000 INFO [09-13|12:46:39.683] INFO [09-13|12:46:39.683] Post-Merge hard forks (timestamp based): INFO [09-13|12:46:39.684] - Shanghai: @1681338455 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md) INFO [09-13|12:46:39.684] INFO [09-13|12:46:39.684] --------------------------------------------------------------------------------------------------------------------------------------------------------- INFO [09-13|12:46:39.684] INFO [09-13|12:46:39.686] Loaded most recent local block number=0 hash=d4e567..cb8fa3 td=17,179,869,184 age=54y5mo3w WARN [09-13|12:46:39.688] Loaded snapshot journal diffs=missing INFO [09-13|12:46:39.688] Resuming state snapshot generation root=d7f897..0f0544 accounts=0 slots=0 storage=0.00B dangling=0 elapsed="34.181µs" INFO [09-13|12:46:39.688] Loaded local transaction journal transactions=0 dropped=0 INFO [09-13|12:46:39.689] Regenerated local transaction journal transactions=0 accounts=0 INFO [09-13|12:46:39.729] Chain post-merge, sync via beacon client INFO [09-13|12:46:39.730] Gasprice oracle is ignoring threshold set threshold=2 WARN [09-13|12:46:39.738] Unclean shutdown detected booted=2023-09-12T15:07:35+0000 age=21h39m4s WARN [09-13|12:46:39.738] Unclean shutdown detected booted=2023-09-13T08:02:05+0000 age=4h44m34s WARN [09-13|12:46:39.739] Engine API enabled protocol=eth |
Following this, the startNode
function executes, paving the way for StartNode
, which is responsible for actually initiating the server. The method stack.Start()
found in cmd/utils/cmd.go:72
will launch the node. Once the server is up and running, the Geth client keeps tabs on the disk space and monitors system signals to determine when to terminate the server.
在此之后, startNode
函数执行,为 StartNode
负责实际启动服务器铺平了道路。在中找到 cmd/utils/cmd.go:72
的方法 stack.Start()
将启动节点。服务器启动并运行后,Geth 客户端会密切关注磁盘空间并监视系统信号以确定何时终止服务器。
Within the Start()
method, the line err := n.openEndpoints()
is responsible to open networking and RPC endpoint. Meanwhile, the n.server.Start()
method, located at node/node.go:269
initiates the p2p discovery and handshake processes. Concurrently, the line err := n.startRPC()
located at node/node.go:273
brings the RPC endpoint to life. The output should resemble the following:
在 Start()
该方法中,该行 err := n.openEndpoints()
负责打开网络和 RPC 终结点。同时, n.server.Start()
位于 的方法 node/node.go:269
启动 p2p 发现和握手过程。同时,位于 的 node/node.go:273
线路 err := n.startRPC()
使 RPC 终结点栩栩如生。输出应类似于以下内容:
1 2 3 4 5 6 7 8 9 |
INFO [09-13|13:56:00.514] Starting peer-to-peer node instance=Geth/v1.12.1-unstable-60ce4e8d-20230810/linux-amd64/go1.20.6 INFO [09-13|13:56:04.989] New local node record seq=1,694,613,193,948 id=72f98ebcedb92640 ip=127.0.0.1 udp=35555 tcp=35555 INFO [09-13|13:56:05.083] Started P2P networking self=enode://9fc6b61a19d99e8a78ae8f8dbd12f27d208ce9b01dd52177fbfee1812a37467b3c3bab49c181b26b240f52bf1ac8afe64915f9b89465a540a74fdcb5e37f2abd@127.0.0.1:35555 INFO [09-13|13:56:05.325] Generating state snapshot root=d7f897..0f0544 at=9a53a5..ad4ba5 accounts=5375 slots=0 storage=247.62KiB dangling=0 elapsed=8.003s eta=28.97s INFO [09-13|13:56:10.187] IPC endpoint opened url=/home/username/.ethereum/geth.ipc INFO [09-13|13:56:10.200] Loaded JWT secret file path=/home/username/.ethereum/geth/jwtsecret crc32=0x3392b636 INFO [09-13|13:56:11.116] WebSocket enabled url=ws://127.0.0.1:8553 INFO [09-13|13:56:11.121] HTTP server started endpoint=127.0.0.1:8553 auth=true prefix= cors=localhost vhosts=localhost |
Once the p2p network layer has been executed successfully, the crucial Ethereum protocol initiates and remains active. Two essential components stand out:
一旦 p2p 网络层成功执行,关键的以太坊协议就会启动并保持活动状态。两个基本组成部分很突出:
txPool
: This manages transactions according to a specified strategy.
txPool
:根据指定的策略管理事务。blockchain
: This encompasses the EVM (Ethereum Virtual Machine) and upholds the chain structure of the blockchain.
blockchain
:这包括EVM(以太坊虚拟机)并维护区块链的链结构。
The rationale for defining the subprotocol as a slice of lifecycle is that Geth also supports other protocols layered over the Devp2p protocol.
将子协议定义为生命周期切片的基本原理是,Geth还支持在Devp2p协议上分层的其他协议。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
// Ethereum implements the Ethereum full node service. type Ethereum struct { config *ethconfig.Config // Handlers txPool *txpool.TxPool blockchain *core.BlockChain handler *handler ethDialCandidates enode.Iterator snapDialCandidates enode.Iterator merger *consensus.Merger // DB interfaces chainDb ethdb.Database // Block chain database eventMux *event.TypeMux engine consensus.Engine accountManager *accounts.Manager bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports closeBloomHandler chan struct{} APIBackend *EthAPIBackend miner *miner.Miner gasPrice *big.Int etherbase common.Address networkID uint64 netRPCService *ethapi.NetAPI p2pServer *p2p.Server lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully } |
To summarize, the steps for starting a Geth client are as follows:
总而言之,启动 Geth 客户端的步骤如下:
- Command Line Parsing: The parser breaks down flags, subcommands, or the configuration file into a
context
.
命令行解析:解析器将标志、子命令或配置文件分解为context
. - Process Context: The command line context is processed, establishing memory cache allowances and, if enabled, metrics that monitor the runtime environment.
处理上下文:处理命令行上下文,建立内存缓存限额,如果启用,则建立监视运行时环境的指标。 - Protocol Stack Assembly: Based on the provided configuration, the protocol stack is assembled into a node struct. Concurrently, interaction methods are incorporated into
ethapi.Backend
.
协议栈组装:根据提供的配置,协议栈组装成节点结构。同时,交互方法被合并到ethapi.Backend
. - Node Initialization:
- P2P Network Layer: Initiates the p2p network layer for node discovery and facilitates basic pre-subprotocol (devp2p) message exchange.
P2P网络层:启动P2P网络层进行节点发现,促进基本的预子协议(devp2p)消息交换。 - RPC Endpoint: This step starts the RPC endpoint.
RPC 终结点:此步骤启动 RPC 终结点。 - Subprotocols Activation: All the specified subprotocols in the lifecycles of the local node are initiated.
子协议激活:启动本地节点生命周期内所有指定的子协议。 - Monitoring: Upon successful initialization, the system begins monitoring disk space and awaits system signals for termination.
监控:成功初始化后,系统开始监控磁盘空间并等待系统信号终止。
- P2P Network Layer: Initiates the p2p network layer for node discovery and facilitates basic pre-subprotocol (devp2p) message exchange.
原文始发于learner L:How Geth starts its server