В предыдущей статье мы представили метод изменения исходного кода для получения вознаграждения за блок в соответствии с консенсусом PoA. Когда есть только один узел, этот метод не вызывает никаких проблем, как только к сети присоединяется новый узел; Добавленные узлы застрянут на этапе синхронизации данных. Так почему же это происходит?
В соответствии с консенсусом PoA,Вообще, блока наград нет.,но в некоторых случаях,нас Может Исправлять Исходный код для настройкиизблокироватьнаградалогика。Например,путем измененияconsensus/clique/clique.go
файлы, которые будут выданы для блокировки производителейнаграда。
// consensus/clique/clique.go
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
if len(txs) != 0 {
miner, err := ecrecover(chain.CurrentHeader(), c.signatures)
if err != nil {
log.Error("Failed to recover miner address", "err", err)
return
}
// награда
state.AddBalance(miner, uint256.NewInt(chain.Config().Clique.Reward*1e18))
}
}
В этом коде,мы проходимecrecover
функция для восстановления адреса производителя блока,И дайте блоку награду. Однако,Когда к сети присоединяется новый узел (будь то узел синхронизации или узел валидатора),Вы столкнетесь с проблемой: новый узел не может выполнить синхронизацию с существующим узлом.,Завис на этапе синхронизации данных.
вопросиз Суть в том, что новый узел не может быть определен как правильный.изблокироватьнаградаадрес。в существующихизлогикасередина,блокироватьнаградаизадресзависит отetherbase
параметризценить,Это приведет к созданию нового узлаизблокироватьнаградаадреси Существующие узлы отличаются,Это приводит к сбою синхронизации.
Конкретно:
miner
Связанныйизпараметр,Система автоматически получит соответствующую информацию из конфигурации в блоке генезиса.miner
адрес,Но если новый узел имеет другую конфигурацию, чем существующий узел,ecrecover
возврат функцииизшахтерадресбудет другим,вызывая сбой синхронизации.Чтобы решить эту проблему,нас Может确保блокироватьнаградаадресизуверенность,То есть каждый узел может Получено из блока генезисатакой жеизблокироватьнаградаадрес。Поскольку каждая сеть блокчейнов имеет уникальныйизблок генезиса,Генезисный блок содержит первоначальную конфигурацию сети.,поэтомунас Может在блок генезисасередина写入блокироватьнаградаизадрес,并确保所有узел在同步时都能使用такой жеизнаградаадрес。
первый,нам нужно быть внутриgenesis.json
ЧжунвэйPoAКонсенсус добавленблокироватьнаградаадрес(coinbases
Поле)инаградаколичество(reward
Поле)。так,Вновь присоединенные узлы могут получить эти конфигурации из генезисного блока.
// params/config.go
// CliqueConfig is the consensus engine configs for proof-of-authority based sealing.
type CliqueConfig struct {
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint
// new
Coinbases []string `json:"coinbases"` // List of coinbase addresses to use for getting rewards
Reward uint64 `json:"reward"` // Reward amount in ETH per block
}
Исправлятьназадизgenesis.json
Показывать Например Вниз:
{
"config": {
"chainId": 12345,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"berlinBlock": 0,
"clique": {
"period": 1,
"epoch": 30000,
"coinbases": [
"0x618C92D30E4a7B21A0D00DC7f5038024752ADFD5",
"0xe23C2c6e7f785e74EB7AAeF96455B78C53adb2E3"
],
"reward": 2
}
},
"difficulty": "1",
"gasLimit": "0xFFFFFFFF",
"extradata": "0x0000000000000000000000000000000000000000000000000000000000000000618C92D30E4a7B21A0D00DC7f5038024752ADFD50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"alloc": {
"618C92D30E4a7B21A0D00DC7f5038024752ADFD5": {
"balance": "10000000000000000000000"
},
"e23C2c6e7f785e74EB7AAeF96455B78C53adb2E3": {
"balance": "10000000000000000000000"
}
}
}
В этой конфигурации:
coinbases
указаны дваадрес,какблокироватьнаградаизполучатель。reward
Укажите каждый блокизнаградаколичество。extradata
Поле Может包含блокировать ВОЗиздополнительные данные。Finalize
Способ получениянаградаадресСледующий,нам нужно изменитьFinalize
метод,使其从блок генезисаиз配置середина动态获取блокироватьнаградаадрес,вместо того, чтобы полагаться наetherbase
илиecrecover
。
// consensus/clique/clique.go
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
// Если транзакции нет, вернитесь напрямую
if len(txs) == 0 {
return
}
decimals := 1e18
// 从блок генезиса配置середина获取блокироватьнаградаадрес
coinbases := chain.Config().Clique.Coinbases
coinbaseLen := len(coinbases)
if coinbaseLen != 0 {
// Рассчитывается на основе номера блокаблокироватьнаградаадрес
index := header.Number.Uint64() % uint64(coinbaseLen)
state.AddBalance(common.HexToAddress(coinbases[index]), uint256.NewInt(chain.Config().Clique.Reward*decimals))
}
}
в этом ИсправлятьназадизFinalize
методсередина:
coinbases
(Прямо сейчасблокироватьнаградаадрессписок)。header.Number
)инаградаадрессписокиздлина,Рассчитать точный адрес,и датьадреспроблеманаграда。После завершения вышеуказанных модификаций кода,нас Нужно перекомпилироватьgeth
клиент,Используйте вместе Исправлятьназадизgenesis.json
файл начать зановоизузел。так,所有узел都会使用从блок генезисасередина读取изнаградаадрес,Вместо того, чтобы полагаться на ручную настройку.