dev模式简要说明
主要用来给开发人员提供一个方便的开发测试环境。在dev模式下,可以轻松的获得以太币,方便发起交易,交易也会被快速的打包,节省时间方便验证。在启动命令里面加一个 --dev
即可启动该开发模式。
启动命令
下面提供一条使用dev模式启动的常用命令
geth --datadir ./data --networkid 1337 --nodiscover --http --http.corsdomain * --http.addr 0.0.0.0 --http.port 41230 --http.api eth,net,web3,personal,admin,miner,txpool,clique,debug --log.debug --verbosity 5 --dev --dev.period 0 --allow-insecure-unlock --log.debug --mine --miner.threads 1 console
dev 模式下面涉及到的一些参数单独说一下:
- --dev 以dev模式启动启动链
- --http.api 增加了一个 clique 的接口。这个接口用来动态调整出块人。
- --dev.period 0 出块时间,如果设置为 0, 那么只有有交易发送到链上的时候才触发出块(也就是说不出空快)。如果非0,则是出块的间隔时间。
相关知识点
- dev模式下面使用的共识算法是clique(即PoA)
- dev模式下面,如果keystore下面没有账号,会帮我们创建一个账号,这个账号默认密码为空。如果有账号或者指定挖矿账号(即出块人的账号),那么你必须将这个账号的密码在启动命令里面传进去,否则账号无法解锁则会启动失败。
- dev模式会打一大笔eth到出块人的账号下面,方便调试。
相关代码
- 账号创建
if list := MakePasswordList(ctx); len(list) > 0 { // Just take the first value. Although the function returns a possible multiple values and // some usages iterate through them as attempts, that doesn't make sense in this setting, // when we're definitely concerned with only one account. passphrase = list[0] } // setEtherbase has been called above, configuring the miner address from command line flags. if cfg.Miner.Etherbase != (common.Address{}) { developer = accounts.Account{Address: cfg.Miner.Etherbase} } else if accs := ks.Accounts(); len(accs) > 0 { developer = ks.Accounts()[0] } else { developer, err = ks.NewAccount(passphrase) if err != nil { Fatalf("Failed to create developer account: %v", err) } } if err := ks.Unlock(developer, passphrase); err != nil { Fatalf("Failed to unlock developer account: %v", err) } log.Info("Using developer account", "address", developer.Address)
// Create a new developer genesis block or reuse existing one
cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
* 创世块的设置
```go
func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
// Override the default period to the user requested one
config := *params.AllCliqueProtocolChanges
config.Clique = ¶ms.CliqueConfig{
Period: period,
Epoch: config.Clique.Epoch,
}
// Assemble and return the genesis with the precompiles and faucet pre-funded
return &Genesis{
Config: &config,
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
GasLimit: 11500000,
BaseFee: big.NewInt(params.InitialBaseFee),
Difficulty: big.NewInt(1),
Alloc: map[common.Address]GenesisAccount{
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity
common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp
common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
},
}
}
-
出块间隔
func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { header := block.Header() // Sealing the genesis block is not supported number := header.Number.Uint64() if number == 0 { return errUnknownBlock } // For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) if c.config.Period == 0 && len(block.Transactions()) == 0 { log.Info("Sealing paused, waiting for transactions") return nil }
搭建一个基于PoA的四节点
dev模式下面只有一个节点,无法验证节点之间的交互。如果有需要,那么可以搭建一个基于PoA共识算法的多节点,大概步骤如下。
创建挖矿账号
使用命令geth --datadir node1 account new
依次创建需要挖矿的账号,想要多少个节点就创建多少个节点。
创建genesis.json文件
使用交互式命令puppeth
(自己编译一下cmd/puppeth下面的代码),根据提示创建一个genesis.json文件。创建出来的genesis.json文件内容类似如下:
{
"config": {
"chainId": 1205,
"homesteadBlock": 0,
"eip150Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"clique": {
"period": 15,
"epoch": 30000
}
},
"nonce": "0x0",
"timestamp": "0x60de826f",
"extraData": "0x000000000000000000000000000000000000000000000000000000000000000023893ab711b8a31f166e5977191a9acb737d49089ae5c0f24355ca814c0c99d7ee9637ec005fae18b3b1a10f515740ecf805c31c5c612935d60ba5eb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x47b7600000",
"difficulty": "0x1",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"23893ab711b8a31f166e5977191a9acb737d4908": {
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
},
"9ae5c0f24355ca814c0c99d7ee9637ec005fae18": {
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
},
"b3b1a10f515740ecf805c31c5c612935d60ba5eb": {
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"baseFeePerGas": null
}
其中extraData里面有初始的出块人列表。alloc里面是默认账号的初始金额。
创建创世块
使用命令geth --datadir node1 init genesis.json
依次创建创世块
启动节点
使用命令./geth --datadir ./node1 --ipcdisable --port 30001 --nodiscover --http --http.corsdomain "*" --http.addr 0.0.0.0 --http.port 41231 --http.api eth,net,web3,personal,admin,miner,txpool,clique --log.debug --verbosity 5 --allow-insecure-unlock console
启动链。参数根据自己需求进行增删。注意这个时候不要加 --dev
参数
解锁账号并开启挖矿
最好是在启动节点的时候将密码传进去直接解锁。
节点互连
由于启动的节点使用了 --nodiscover
参数。所以启动之后还没有链接起来,可以使用 RPC 接口 admin_addPeer
将节点互联起来。每次启动这么弄都很麻烦。可以在节点的数据库里面放一个 static-nodes.json
文件,跟目录 geth
同级即可。 static-nodes.json
文件内容大概如下:
[
"enode://4d87f6cd87680adb4b51a80ed6bc7125640a29a953b7fd9a3e4ab21009a99436faa16bbb359994bcc9b89e52869abd3b0dc3908e2a368f49eb553609276836b2@127.0.0.1:30001",
"enode://a3c958413831b2561273b6d2cc21c818e2675443872ba2077a66264d253d7525eb5b895647c37d3249439608506eb0fb99987fe0fbac1c174acb2bf996e658dc@127.0.0.1:30002",
"enode://d581f48b7c4902b91f9709b7fa8149d10a5f11a1078e196f0d4bdaf89e4b1be43b7c5115e61976384ea96a2dd6f7ca96e500e571221302094c0b18b31caddea6@127.0.0.1:30003",
"enode://430b1342533e9f0db719bd0eedd46cf5f4b163786e7a0238afccce771869a16604eb67106d288a152b5c814b7fb4cd184ac5cf330761a8f6e624fe2e554eb89c@127.0.0.1:30004"
]