POA模式中,无法区分哪个签名者是coinbase,且poa共识下 也不需要coinbase作为接受出块奖励,遂在 consensus/clique/clique.go Prepare() 方法中,将coinbase 置为空。
2021-1-5 更新
发现在官方的POA测试网络上,每个块的miner字段不为空,经过一番测试后,对上面做出补充,POA共识下,block结构中的miner字段不具有实体的意义,但是结合POA的出块模式,每一个块确实是由一个地址签名授权发出的,可以通过签名数据获取签名地址,进而获得该区块的授权地址
package main
import (
"context"
"fmt"
"github.com/ebfe/keccak"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"log"
// "math/big"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
client, err := ethclient.Dial("ws://192.168.217.128:8546")
if err != nil {
log.Fatal(err)
}
header, err := client.HeaderByNumber(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
block, err := client.BlockByNumber(context.Background(), header.Number)
if err != nil {
log.Fatal(err)
}
pubkey, err := crypto.SigToPub(sigHash(block.Header()).Bytes(), block.Extra()[32:])
fmt.Println(err)
fmt.Println(crypto.PubkeyToAddress(*pubkey).Hex())
}
func sigHash(header *types.Header) (hash common.Hash) {
hasher := keccak.New256()
rlp.Encode(hasher, []interface{}{
header.ParentHash,
header.UncleHash,
header.Coinbase,
header.Root,
header.TxHash,
header.ReceiptHash,
header.Bloom,
header.Difficulty,
header.Number,
header.GasLimit,
header.GasUsed,
header.Time,
header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
header.MixDigest,
header.Nonce,
})
hasher.Sum(hash[:0])
return hash
}