[ethereum源码分析](4) ethereum运行开启console
前言
在上一章我们介绍了 ethereum初始化指令 ,包括了系统是如何调用指令和指令的执行。在本章节我们将会介绍 geth --datadir dev/data/ --networkid console 指令。
指令分析
指令: geth --datadir dev/data/ --networkid console
介绍:上面的指令主要的工作为:
- 运行eth程序
- 开启控制台
分析:
- --datadir :指定eth的数据存储地址为 dev/data/
- --networkid :指定eth的网络编号为 ,与其他eth网络区分,这个是建立公网的关键。
代码分析
接下来就让我们进入代码分析阶段,至于系统是如何执行命令的在前一章已经介绍过了,这里就不多在做介绍。
通过上一章的介绍我们知道,eth系统会执行以下的指令:
consoleCommand = cli.Command{
Action: utils.MigrateFlags( localConsole ),
Name: "console",
Usage: "Start an interactive JavaScript environment",
Flags: append(append(append(nodeFlags, rpcFlags...), consoleFlags...), whisperFlags...),
Category: "CONSOLE COMMANDS",
Description: `
The Geth console is an interactive shell for the JavaScript runtime environment
which exposes a node admin interface as well as the Ðapp JavaScript API.
See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console.`,
}
上面就是我们 command 指令的数据结构,由上面的代码可知,最终代码会执行 localConsole 这个函数,那么下面就让我们来跟进这个函数:
// localConsole starts a new geth node, attaching a JavaScript console to it at the
// same time.
func localConsole(ctx *cli.Context) error {
// Create and start the node based on the CLI flags
node := makeFullNode(ctx)//初始化一些配置信息
startNode(ctx, node)//开启节点
defer node.Stop() // Attach to the newly started node and start the JavaScript console
client, err := node.Attach()
if err != nil {
utils.Fatalf("Failed to attach to the inproc geth: %v", err)
}
config := console.Config{
DataDir: utils.MakeDataDir(ctx),
DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
Client: client,
Preload: utils.MakeConsolePreloads(ctx),
} console, err := console.New(config)
if err != nil {
utils.Fatalf("Failed to start the JavaScript console: %v", err)
}
defer console.Stop(false) // If only a short execution was requested, evaluate and return
if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
console.Evaluate(script)
return nil
}
// Otherwise print the welcome screen and enter interactive mode
console.Welcome()
console.Interactive()//进入命令行 return nil
}
上面的代码首先执行了 makeFullNode(ctx) 。下面让我们来跟进代码:
func makeFullNode(ctx *cli.Context) *node.Node {
stack, cfg := makeConfigNode(ctx)//在这里构造了一个节点 utils.RegisterEthService(stack, &cfg.Eth) if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
}
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
shhEnabled := enableWhisper(ctx)
shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
if shhEnabled || shhAutoEnabled {
if ctx.GlobalIsSet(utils.WhisperMaxMessageSizeFlag.Name) {
cfg.Shh.MaxMessageSize = uint32(ctx.Int(utils.WhisperMaxMessageSizeFlag.Name))
}
if ctx.GlobalIsSet(utils.WhisperMinPOWFlag.Name) {
cfg.Shh.MinimumAcceptedPOW = ctx.Float64(utils.WhisperMinPOWFlag.Name)
}
utils.RegisterShhService(stack, &cfg.Shh)
} // Add the Ethereum Stats daemon if requested.
if cfg.Ethstats.URL != "" {
utils.RegisterEthStatsService(stack, cfg.Ethstats.URL)
}
return stack
}
上面的代码首先构造了一个节点,那么他是如何去构造这个节点的呢,让我们来看一看 makeConfigNode(ctx) 这个函数:
func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
// Load defaults.
cfg := gethConfig{
Eth: eth.DefaultConfig,//配置eth的一些基本信息,里面设置了NetWorkId(默认值为1,这也是eth的主网)的信息
Shh: whisper.DefaultConfig,//里面配置了两个参数:1.MaxMessageSize 2.MinimumAcceptedPOW(POW:Proof of Work,工作量证明),暂时不知道有什么用处?
Node: defaultNodeConfig(),//这了初始化了节点的配置,主要有网络的一些配置,还有就是数据的存储路径
Dashboard: dashboard.DefaultConfig,//仪表盘的配置:端口号,刷新时间
} // Load config file.
if file := ctx.GlobalString(configFileFlag.Name); file != "" {
if err := loadConfig(file, &cfg); err != nil {
utils.Fatalf("%v", err)
}
} // Apply flags.
utils.SetNodeConfig(ctx, &cfg.Node)//这里设置了P2P,IPC,HTTP,WS,DataDir,KeyStoreDir的值
stack, err := node.New(&cfg.Node)
if err != nil {
utils.Fatalf("Failed to create the protocol stack: %v", err)
}
utils.SetEthConfig(ctx, stack, &cfg.Eth)//这里设置NetWorkId的值
if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) {
cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name)
} utils.SetShhConfig(ctx, stack, &cfg.Shh)
utils.SetDashboardConfig(ctx, &cfg.Dashboard) return stack, cfg
}
当 makeFullNode(ctx) 执行完以后,接下来执行的就是 startNode(ctx, node) ,它的代码如下:
// startNode boots up the system node and all registered protocols, after which
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// miner.
func startNode(ctx *cli.Context, stack *node.Node) {
debug.Memsize.Add("node", stack) // Start up the node itself
utils.StartNode(stack)//开启节点,主要做了开启P2P网络,开启UDP监听(监听30303端口),开启RLPx监听。 // Unlock any account specifically requested
ks := stack.AccountManager().Backends(keystore.KeyStoreType)[].(*keystore.KeyStore) passwords := utils.MakePasswordList(ctx)
unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
for i, account := range unlocks {
if trimmed := strings.TrimSpace(account); trimmed != "" {
unlockAccount(ctx, ks, trimmed, i, passwords)
}
}
// Register wallet event handlers to open and auto-derive wallets
events := make(chan accounts.WalletEvent, )
stack.AccountManager().Subscribe(events) go func() {
// Create a chain state reader for self-derivation
rpcClient, err := stack.Attach()
if err != nil {
utils.Fatalf("Failed to attach to self: %v", err)
}
stateReader := ethclient.NewClient(rpcClient) // Open any wallets already attached
for _, wallet := range stack.AccountManager().Wallets() {
if err := wallet.Open(""); err != nil {
log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err)
}
}
// Listen for wallet event till termination
for event := range events {
switch event.Kind {
case accounts.WalletArrived:
if err := event.Wallet.Open(""); err != nil {
log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err)
}
case accounts.WalletOpened:
status, _ := event.Wallet.Status()
log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) if event.Wallet.URL().Scheme == "ledger" {
event.Wallet.SelfDerive(accounts.DefaultLedgerBaseDerivationPath, stateReader)
} else {
event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
} case accounts.WalletDropped:
log.Info("Old wallet dropped", "url", event.Wallet.URL())
event.Wallet.Close()
}
}
}()
// Start auxiliary services if enabled
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) {
// Mining only makes sense if a full Ethereum node is running
if ctx.GlobalBool(utils.LightModeFlag.Name) || ctx.GlobalString(utils.SyncModeFlag.Name) == "light" {
utils.Fatalf("Light clients do not support mining")
}
var ethereum *eth.Ethereum
if err := stack.Service(ðereum); err != nil {
utils.Fatalf("Ethereum service not running: %v", err)
}
// Use a reduced number of threads if requested
if threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name); threads > {
type threaded interface {
SetThreads(threads int)
}
if th, ok := ethereum.Engine().(threaded); ok {
th.SetThreads(threads)
}
}
// Set the gas price to the limits from the CLI and start mining
ethereum.TxPool().SetGasPrice(utils.GlobalBig(ctx, utils.GasPriceFlag.Name))
if err := ethereum.StartMining(true); err != nil {
utils.Fatalf("Failed to start mining: %v", err)
}
}
}
[ethereum源码分析](4) ethereum运行开启console的更多相关文章
- [ethereum源码分析](3) ethereum初始化指令
前言 在上一章介绍了关于区块链的一些基础知识,这一章会分析指令 geth --datadir dev/data/02 init private-geth/genesis.json 的源码,若你的eth ...
- [ethereum源码分析](2) ethereum基础知识
前言 上一章我们介绍了如何搭建ethereum的debug环境.为了更深入的了解ethereum,我们需要了解一些ethereum的相关的知识,本章我们将介绍这些知识. ethereum相关知识 在学 ...
- Appium Server 源码分析之启动运行Express http服务器
通过上一个系列Appium Android Bootstrap源码分析我们了解到了appium在安卓目标机器上是如何通过bootstrap这个服务来接收appium从pc端发送过来的命令,并最终使用u ...
- [ethereum源码分析](5) 创建新账号
前言 在上一章我们介绍了 ethereum运行开启console 的过程,那么在这一章我们将会介绍如何在以太坊中创建一个新的账号.以下的理解可能存在错误,如果各位大虾发现错误,还望指正. 指令分析 指 ...
- Appium Android Bootstrap源码分析之启动运行
通过前面的两篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>和<Appium Android Bootstrap源码分析之命令解析 ...
- [ethereum源码分析](1) dubug环境搭建
前言 因为最近云小哥哥换了一份工作,新公司比较忙,所以一直没有更新新的博客.云小哥哥新的公司是做区块链的,最近在学习区块链相关的东西(也算是乘坐上了区块链这艘大船).本博客是记录我搭建ethereum ...
- go ethereum源码分析 PartIV Transaction相关
核心数据结构: core.types.transaction.go type Transaction struct { data txdata // caches hash atomic.Value ...
- Ethereum 源码分析之 accounts
一.Account // Account represents an Ethereum account located at a specific location defined // by the ...
- Ethereum 源码分析之框架
accounts 实现了一个高等级的以太坊账户管理 bmt 二进制的默克尔树的实现 build 主要是编译和构建的一些脚本和配置 cmd ...
随机推荐
- 第二章 Git
1.安装 这个就不必细说了 2.安装完后还要进行一步设置. 在命令行输入: git config --global user.name "Your Name" git config ...
- python 开启进程两种方法 multiprocessing模块 介绍
一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu\_count\(\)查看),在python中大部分情况需要使用多进 ...
- springboot + mybaits + oracle 项目
1.pom设置 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...
- [转帖]青岛uber偷拍设备
爱彼迎民宿路由器暗藏摄像头:官方回应已移除房源 https://www.cnbeta.com/articles/tech/844233.htm 罚款 就是搞笑啊.. 不过现在偷拍设备真多... 5月5 ...
- PostgreSQL设计之初的大量论文
引自:https://www.docs4dev.com/docs/zh/postgre-sql/11.2/reference/biblio.html#STON86 该网站是一个PostgreSQL手册 ...
- Mysql 5.7存储过程的学习
存储过程:对sql的封装和重用,经编译创建并保存在数据库中,通过指定存储过程的名字并给定参数(需要时)来调用执行. 优缺点: (1) 优点: 执行速度快------存储过程只在创建时进行编译,以后每次 ...
- Java8---函数式编程-示例
// Java8函数式编程示例—(Predicate.Stream.Optional) https://blog.csdn.net/weixin_41950473/article/details/84 ...
- oracle跟SQL Server 2005 的区别
Oracle与Sql server的区别 一直搞不明白Oracle数据库和sql server的区别,今天我特意查资料把他们的区别整理出来 Oracle数据库:Oracle Database,又名 ...
- 块设备驱动——ramblock
一. 什么是块设备. 1.1. 一种具有一定结构的随机存取设备,对这种设备的读写是按块进行的,他使用缓冲区来存放暂时的数据,待条件成熟后,从缓存一次性写入设备或者从设备一次性读到缓冲区.可以随机访问, ...
- LINQ 推迟查询的执行
LINQ 在运行期间定义查询表达式时.查询就不会运行.查询会在迭代数据项是运行,例如: static void Main(string[] args) { List<string> lis ...