GetBlocks
区块Header结构
type Bloom [256]byte
type BlockNonce [8]byte
// Header represents a block header in the Ethereum blockchain.
type Header struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Number *big.Int `json:"number" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
Time uint64 `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
// BaseFee was added by EIP-1559 and is ignored in legacy headers.
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
// WithdrawalsHash was added by EIP-4895 and is ignored in legacy headers.
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
// BlobGasUsed was added by EIP-4844 and is ignored in legacy headers.
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
// ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers.
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
// ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
// RequestsHash was added by EIP-7685 and is ignored in legacy headers.
RequestsHash *common.Hash `json:"requestsRoot" rlp:"optional"`
}
返回特定区块的区块头信息-BlockHash
返回最新区块的区块头信息,不包含具体的交易区块体
package main
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"log"
"math/big"
)
var (
client *ethclient.Client
err error
)
func init() {
client, err = ethclient.Dial("https://eth.llamarpc.com")
if err != nil {
log.Fatal(err)
}
}
func checkError(err error) {
if err != nil {
log.Fatal(err)
}
}
func main() {
var ctx = context.Background()
var blockhash = "0x6d7977fbf9333267c5bc25b596eacc2ef89461289e078dd7283c6872008646bc"
headers, err := getBlockHeader(ctx, common.HexToHash(blockhash))
checkError(err)
fmt.Println(fmt.Sprintf("Latest block header info = %s", headers))
var header types.Header
if err = header.UnmarshalJSON([]byte(headers)); err != nil {
log.Fatalf("decode error: %v ", err)
}
fmt.Println(header.Number)
}
func getBlockHeader(ctx context.Context, hash common.Hash) (string, error) {
header, err := client.HeaderByHash(ctx, hash)
if err != nil {
if errors.Is(err, ethereum.NotFound) {
return "", errors.New("non-exist blockHash")
}else{
checkError(err)
}
}
headerBytes, err := header.MarshalJSON()
if err != nil {
return string(headerBytes), err
}
return string(headerBytes), err
}
Examples:
{
"parentHash":"0x220987cbab8e6bc276671b33b8d6f1207dab1fc80ffe58165b1b070d34f73fc7",
"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"miner":"0x1f9090aae28b8a3dceadf281b0f12828e676c326",
"stateRoot":"0x2e4cfaff4b5f165bd7178091f6b13ff74e5492278fdc1ff1efbe9866347cedc2",
"transactionsRoot":"0x0558cbcf91c9de46e950988836c0e305f335292a1f821cff5505c12e79e5ada9",
"receiptsRoot":"0x98b457f5ac24528e16d6c26107ac3f210f4d820bbfe587e8df5562457f950683",
"logsBloom":"0x0000004000000004000010000200000030000100000000001000000000000000000000000000000000000000200001002200000008002000028000000000000000000008010000080000020800000000000000900000000000000014002000000008000000200220000000000000000002000000000400000000001000080000002000000a0000000000000000200000000080000000000000000000001000002500000000000000000000a0000000800000040000000000000000000000000001000022000808000000080000400800000000000000000000000000000020020200282000040000000000000000000000201000000000800000000000000200",
"difficulty":"0x0",
"number":"0x1447225",
"gasLimit":"0x1c9c380",
"gasUsed":"0xe16bf",
"timestamp":"0x6744146f",
"extraData":"0x7273796e632d6275696c6465722e78797a",
"mixHash":"0x1f49ed8baffafa6b5fd66b1f2577f47eb508a6d0c5444c28b588b5e76a9a40c2",
"nonce":"0x0000000000000000",
"baseFeePerGas":"0x1ba8af27d",
"withdrawalsRoot":"0x80ecd553069724318de66efd3099be1f97f62df4ff3fb94c30f16c3aee275f62",
"blobGasUsed":"0x0",
"excessBlobGas":"0x4b20000",
"parentBeaconBlockRoot":"0xffd644329d46413352298de6bde7ca71752862a2bae34f0e3ead6970a3e9912a",
"requestsRoot":null,
"hash":"0x6d7977fbf9333267c5bc25b596eacc2ef89461289e078dd7283c6872008646bc"
}
返回特定区块的区块头信息-BlockHeight
func checkError(err error) {
if err != nil {
log.Fatalf("error = %v", err)
}
}
func main() {
var ctx = context.Background()
headers, err := getTargetBlockHeader(ctx, big.NewInt(-2))//nil is the latest block height
if err != nil {
if errors.Is(err, ethereum.NotFound) {
fmt.Println("invalid block height")
} else {
checkError(err)
}
} else {
headerBytes, err := headers.MarshalJSON()
if err == nil {
fmt.Println(fmt.Sprintf("Target block header info = %s", string(headerBytes)))
var header types.Header
if err = header.UnmarshalJSON([]byte(string(headerBytes))); err != nil {
log.Fatalf("decode error: %v ", err)
}
fmt.Println(header.Number)
} else {
checkError(err)
}
}
}
func getTargetBlockHeader(ctx context.Context, number *big.Int) (*types.Header, error) {
header, err := client.HeaderByNumber(ctx, number)
return header, err
}
BlocksDataEncode
rlp
编码区块信息
func main() {
var ctx = context.Background()
hash := "0x6d7977fbf9333267c5bc25b596eacc2ef89461289e078dd7283c6872008646bc"
blockInfo := getBlock(ctx, common.HexToHash(hash))
fmt.Println(fmt.Printf("Blocks data %s within block hash = %s", blockInfo, hash))
txs := decodeBlock(blockInfo)
fmt.Println(txs)
}
func getBlock(ctx context.Context, hash common.Hash) string {
block, err := client.BlockByHash(ctx, hash)
if err != nil {
if errors.Is(err, ethereum.NotFound) {
return "", errors.New("non-exist blockHash")
}else{
checkError(err)
}
}
BlockEnc, err := rlp.EncodeToBytes(&block)
if err != nil {
log.Fatalf("Encode blocks err = %v", err)
}
blockStr := common.Bytes2Hex(BlockEnc)
return blockStr
}
func decodeBlock(blockInfo string) []string {
blockEnc := common.FromHex(blockInfo)
var block types.Block
if err := rlp.DecodeBytes(blockEnc, &block); err != nil {
log.Fatalf("decode error: %v", err)
}
tx := make([]string, len(block.Body().Transactions))
for _, trans := range block.Body().Transactions {
transB, _ := trans.MarshalJSON()
tx = append(tx, string(transB))
}
return tx
//check := func(f string, got, want interface{}) {
// if !reflect.DeepEqual(got, want) {
// log.Fatalf("%s mismatch: got %v, want %v", f, got, want)
// }
//}
}
BlocksReceipt
获取当前区块体中全部交易的收据信息,用于判断每条交易的执行状态
func checkError(err error) {
if err != nil {
log.Fatalf("error = %v", err)
}
}
func main() {
var ctx = context.Background()
hash := "0x6d7977fbf9333267c5bc25b596eacc2ef89461289e078dd7283c6872008646bc"
var filter rpc.BlockNumberOrHash = rpc.BlockNumberOrHashWithHash(common.HexToHash(hash), false)
count := getBlockReceipt(ctx, filter)
fmt.Println(count)
}
func getBlockReceipt(ctx context.Context, filter rpc.BlockNumberOrHash) int {
receipts, err := client.BlockReceipts(ctx, filter)
if err != nil {
if errors.Is(err, ethereum.NotFound) {
fmt.Println("invalid block height")
} else {
checkError(err)
}
}
return len(receipts)
}