12.14 普通节点问题push汇总 - Agzs/geth-pbft-study GitHub Wiki

普通节点问题

本次push主要解决了普通节点的适用问题,即普通节点和pbft的共识节点使用同一套系统,而普通节点不需要rocksDB数据库,也不需要pbft共识,只是进行交易和同步区块。

1. cmd/geth/main.go

init()函数中为viper增加config.yaml的新路经为”$HOME/.geth-pbft",相关操作如下:

        // Path to look for the config file in based on HOME
	home := os.Getenv("HOME") //=>GOPATH -> HOME --Agzs
	for _, p := range filepath.SplitList(home) {
		pbftpath := filepath.Join(p, ".geth-pbft") //=>11.13 path--Agzs
		viper.AddConfigPath(pbftpath)
	}

2. consensus/pbft/api.go

Propose()Discard()函数中追加条件,即这两个函数仅限pbft共识的节点调用,普通节点调用不起作用,如下:

func (api *API) Propose(address common.Address, auth bool) {
	if api.pbft.GetID() == DefaultPbftID { //=>add for ordinary node --Agzs 12.13
		log.Warn("Sorry, you are not VP, can't do this!!!")
		return
	}
	api.pbft.lock.Lock()
	defer api.pbft.lock.Unlock()

	api.pbft.proposals[address] = auth
}

其中DefaultPbftID为默认的pbftID,在geth指令中缺省--pbftid X时起作用,效果如下:

> pbft.propose("0x079aafa464a201cf265850d852457812766bf549",true)
WARN [12-15|08:43:18] Sorry, you are not VP, can't do this!!! 
null
> 
> pbft.propose("0x079aafa464a201cf265850d852457812766bf549",false)
WARN [12-15|08:43:29] Sorry, you are not VP, can't do this!!! 
null
> 
> pbft.discard("0x079aafa464a201cf265850d852457812766bf549")
WARN [12-15|08:44:39] Sorry, you are not VP, can't do this!!! 
null
> 

3. consensus/pbft/pbft.go

  1. 添加全局变量,用于在geth指令中缺省--pbftid X时,为普通用户指定无效的pbftID
const DefaultPbftID = 1000 //=> set DefaultPbftID to 1000

该变量在多处被调用,主要用于判断当前运行的节点是否为普通节点

  1. func New(id uint64, config *params.PBFTConfig, db ethdb.Database) *PBFT{}中添加普通节点操作,即普通节点不需要初始化pbftCore实例和其相关的其他操作。
func New(id uint64, config *params.PBFTConfig, db ethdb.Database) *PBFT{
        ....
        if pb.config.Epoch == 0 {
		pb.config.Epoch = epochLength
	}
	if pb.config.Period == 0 {
		pb.config.Period = blockPeriod
	}

	if pb.id == DefaultPbftID { //=> add for ordinary node. --Agzs 12.13
		return pb
	}

	pb.manager.SetReceiver(pb) /// Need to implement ProcessEvent. --Zhiguo
	etf := events.NewTimerFactoryImpl(pb.manager)
        ....
}
  1. 凡涉及c.pbft.XXXX均需要在其前添加是否为普通节点的判断,原因是普通节点不需要初始化pbftCore实例,如果不添加判断的话,会导致空指针错误

  2. 修改seal()函数中的条件,使普通节点在pbft共识中无法进行挖矿

> miner.start()
INFO [12-15|08:44:52] Transaction pool price threshold updated price=18000000000
INFO [12-15|08:44:52] Starting mining operation 
null
> INFO [12-15|08:44:52] Commit new mining work                   number=20 txs=0 uncles=0 elapsed=107.142µs
WARN [12-15|08:44:52] Block sealing failed                     err="not signer(primary and backup), cannot issue Seal"
  1. config.yaml文件追加公共路径“HOME/.geth-pbft`,用于配置文件的查找

4. core/db/db.go

添加全局变量RunningFlag,用于标记rocksDB是否启动,用于后期数据库的关闭

5. eth/backend.go

func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {}函数中,添加普通节点的判断,普通节点不会启动rocksDB数据库,只有pbft共识的节点才会启动rocksDB数据库;相应地,只有rocksDB数据库处于开启状态(RunningFlag == true,结束时才能关闭数据库

6. config.go

DefaultConfig中的PbftId由 0 修改为DefaultPbftID,用于区别普通节点和共识节点

7. handler.go

  1. NewProtocolManager()中的PBFT分支中添加普通节点判断,普通节点不用设置commChanmanager

  2. func (pm *ProtocolManager) handle(p *peer) error {}节点成功连接后,追加普通节点广播自身enode操作,用于普通节点间的两两互连