mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 19:30:44 +00:00
feat: add eth/62, eth/63, xdpos2 protocol support
- Added ETH62, ETH63, XDPOS2 protocol version constants - Added handler maps for eth/62, eth/63, xdpos2 - Implemented GetNodeData/NodeData handlers for eth/63 - Added stub handlers for XDPoS2 consensus messages (VoteMsg, TimeoutMsg, SyncInfoMsg) - Added NodeDataPacket, VotePacket, TimeoutPacket, SyncInfoPacket types - Added SendNodeData method to Peer XDC mainnet uses eth/62, eth/63, and xdpos2 protocols. Part4 now advertises support for these versions.
This commit is contained in:
parent
73edcf6927
commit
93bbb7c130
8 changed files with 1223 additions and 21 deletions
427
common/hexutil/json.go.bak
Normal file
427
common/hexutil/json.go.bak
Normal file
|
|
@ -0,0 +1,427 @@
|
|||
// Copyright 2016 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package hexutil
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
var (
|
||||
bytesT = reflect.TypeFor[Bytes]()
|
||||
bigT = reflect.TypeFor[*Big]()
|
||||
uintT = reflect.TypeFor[Uint]()
|
||||
uint64T = reflect.TypeFor[Uint64]()
|
||||
u256T = reflect.TypeFor[*uint256.Int]()
|
||||
)
|
||||
|
||||
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
|
||||
// The empty slice marshals as "0x".
|
||||
type Bytes []byte
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler
|
||||
func (b Bytes) MarshalText() ([]byte, error) {
|
||||
result := make([]byte, len(b)*2+2)
|
||||
copy(result, `0x`)
|
||||
hex.Encode(result[2:], b)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (b *Bytes) UnmarshalJSON(input []byte) error {
|
||||
if !isString(input) {
|
||||
return errNonString(bytesT)
|
||||
}
|
||||
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT)
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||
func (b *Bytes) UnmarshalText(input []byte) error {
|
||||
raw, err := checkText(input, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dec := make([]byte, len(raw)/2)
|
||||
if _, err = hex.Decode(dec, raw); err != nil {
|
||||
err = mapError(err)
|
||||
} else {
|
||||
*b = dec
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// String returns the hex encoding of b.
|
||||
func (b Bytes) String() string {
|
||||
return Encode(b)
|
||||
}
|
||||
|
||||
// ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type.
|
||||
func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" }
|
||||
|
||||
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
|
||||
func (b *Bytes) UnmarshalGraphQL(input interface{}) error {
|
||||
var err error
|
||||
switch input := input.(type) {
|
||||
case string:
|
||||
data, err := Decode(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*b = data
|
||||
default:
|
||||
err = fmt.Errorf("unexpected type %T for Bytes", input)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out
|
||||
// determines the required input length. This function is commonly used to implement the
|
||||
// UnmarshalJSON method for fixed-size types.
|
||||
func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error {
|
||||
if !isString(input) {
|
||||
return errNonString(typ)
|
||||
}
|
||||
return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ)
|
||||
}
|
||||
|
||||
// UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out
|
||||
// determines the required input length. This function is commonly used to implement the
|
||||
// UnmarshalText method for fixed-size types.
|
||||
func UnmarshalFixedText(typname string, input, out []byte) error {
|
||||
raw, err := checkText(input, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(raw)/2 != len(out) {
|
||||
return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
|
||||
}
|
||||
// Pre-verify syntax before modifying out.
|
||||
for _, b := range raw {
|
||||
if decodeNibble(b) == badNibble {
|
||||
return ErrSyntax
|
||||
}
|
||||
}
|
||||
hex.Decode(out, raw)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The
|
||||
// length of out determines the required input length. This function is commonly used to
|
||||
// implement the UnmarshalText method for fixed-size types.
|
||||
func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error {
|
||||
raw, err := checkText(input, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(raw)/2 != len(out) {
|
||||
return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
|
||||
}
|
||||
// Pre-verify syntax before modifying out.
|
||||
for _, b := range raw {
|
||||
if decodeNibble(b) == badNibble {
|
||||
return ErrSyntax
|
||||
}
|
||||
}
|
||||
hex.Decode(out, raw)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Big marshals/unmarshals as a JSON string with 0x prefix.
|
||||
// The zero value marshals as "0x0".
|
||||
//
|
||||
// Negative integers are not supported at this time. Attempting to marshal them will
|
||||
// return an error. Values larger than 256bits are rejected by Unmarshal but will be
|
||||
// marshaled without error.
|
||||
type Big big.Int
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler
|
||||
func (b Big) MarshalText() ([]byte, error) {
|
||||
return []byte(EncodeBig((*big.Int)(&b))), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (b *Big) UnmarshalJSON(input []byte) error {
|
||||
if !isString(input) {
|
||||
return errNonString(bigT)
|
||||
}
|
||||
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT)
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler
|
||||
func (b *Big) UnmarshalText(input []byte) error {
|
||||
raw, err := checkNumberText(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(raw) > 64 {
|
||||
return ErrBig256Range
|
||||
}
|
||||
words := make([]big.Word, len(raw)/bigWordNibbles+1)
|
||||
end := len(raw)
|
||||
for i := range words {
|
||||
start := end - bigWordNibbles
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
for ri := start; ri < end; ri++ {
|
||||
nib := decodeNibble(raw[ri])
|
||||
if nib == badNibble {
|
||||
return ErrSyntax
|
||||
}
|
||||
words[i] *= 16
|
||||
words[i] += big.Word(nib)
|
||||
}
|
||||
end = start
|
||||
}
|
||||
var dec big.Int
|
||||
dec.SetBits(words)
|
||||
*b = (Big)(dec)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToInt converts b to a big.Int.
|
||||
func (b *Big) ToInt() *big.Int {
|
||||
return (*big.Int)(b)
|
||||
}
|
||||
|
||||
// String returns the hex encoding of b.
|
||||
func (b *Big) String() string {
|
||||
return EncodeBig(b.ToInt())
|
||||
}
|
||||
|
||||
// ImplementsGraphQLType returns true if Big implements the provided GraphQL type.
|
||||
func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" }
|
||||
|
||||
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
|
||||
func (b *Big) UnmarshalGraphQL(input interface{}) error {
|
||||
var err error
|
||||
switch input := input.(type) {
|
||||
case string:
|
||||
return b.UnmarshalText([]byte(input))
|
||||
case int32:
|
||||
var num big.Int
|
||||
num.SetInt64(int64(input))
|
||||
*b = Big(num)
|
||||
default:
|
||||
err = fmt.Errorf("unexpected type %T for BigInt", input)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// U256 marshals/unmarshals as a JSON string with 0x prefix.
|
||||
// The zero value marshals as "0x0".
|
||||
type U256 uint256.Int
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler
|
||||
func (b U256) MarshalText() ([]byte, error) {
|
||||
u256 := (*uint256.Int)(&b)
|
||||
return []byte(u256.Hex()), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (b *U256) UnmarshalJSON(input []byte) error {
|
||||
// The uint256.Int.UnmarshalJSON method accepts "dec", "0xhex"; we must be
|
||||
// more strict, hence we check string and invoke SetFromHex directly.
|
||||
if !isString(input) {
|
||||
return errNonString(u256T)
|
||||
}
|
||||
// The hex decoder needs to accept empty string ("") as '0', which uint256.Int
|
||||
// would reject.
|
||||
if len(input) == 2 {
|
||||
(*uint256.Int)(b).Clear()
|
||||
return nil
|
||||
}
|
||||
err := (*uint256.Int)(b).SetFromHex(string(input[1 : len(input)-1]))
|
||||
if err != nil {
|
||||
return &json.UnmarshalTypeError{Value: err.Error(), Type: u256T}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler
|
||||
func (b *U256) UnmarshalText(input []byte) error {
|
||||
// The uint256.Int.UnmarshalText method accepts "dec", "0xhex"; we must be
|
||||
// more strict, hence we check string and invoke SetFromHex directly.
|
||||
return (*uint256.Int)(b).SetFromHex(string(input))
|
||||
}
|
||||
|
||||
// String returns the hex encoding of b.
|
||||
func (b *U256) String() string {
|
||||
return (*uint256.Int)(b).Hex()
|
||||
}
|
||||
|
||||
// Uint64 marshals/unmarshals as a JSON string with 0x prefix.
|
||||
// The zero value marshals as "0x0".
|
||||
type Uint64 uint64
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler.
|
||||
func (b Uint64) MarshalText() ([]byte, error) {
|
||||
buf := make([]byte, 2, 10)
|
||||
copy(buf, `0x`)
|
||||
buf = strconv.AppendUint(buf, uint64(b), 16)
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (b *Uint64) UnmarshalJSON(input []byte) error {
|
||||
if !isString(input) {
|
||||
return errNonString(uint64T)
|
||||
}
|
||||
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T)
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler
|
||||
func (b *Uint64) UnmarshalText(input []byte) error {
|
||||
raw, err := checkNumberText(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(raw) > 16 {
|
||||
return ErrUint64Range
|
||||
}
|
||||
var dec uint64
|
||||
for _, byte := range raw {
|
||||
nib := decodeNibble(byte)
|
||||
if nib == badNibble {
|
||||
return ErrSyntax
|
||||
}
|
||||
dec *= 16
|
||||
dec += nib
|
||||
}
|
||||
*b = Uint64(dec)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the hex encoding of b.
|
||||
func (b Uint64) String() string {
|
||||
return EncodeUint64(uint64(b))
|
||||
}
|
||||
|
||||
// ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type.
|
||||
func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" }
|
||||
|
||||
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
|
||||
func (b *Uint64) UnmarshalGraphQL(input interface{}) error {
|
||||
var err error
|
||||
switch input := input.(type) {
|
||||
case string:
|
||||
return b.UnmarshalText([]byte(input))
|
||||
case int32:
|
||||
*b = Uint64(input)
|
||||
default:
|
||||
err = fmt.Errorf("unexpected type %T for Long", input)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Uint marshals/unmarshals as a JSON string with 0x prefix.
|
||||
// The zero value marshals as "0x0".
|
||||
type Uint uint
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler.
|
||||
func (b Uint) MarshalText() ([]byte, error) {
|
||||
return Uint64(b).MarshalText()
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (b *Uint) UnmarshalJSON(input []byte) error {
|
||||
if !isString(input) {
|
||||
return errNonString(uintT)
|
||||
}
|
||||
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT)
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||
func (b *Uint) UnmarshalText(input []byte) error {
|
||||
var u64 Uint64
|
||||
err := u64.UnmarshalText(input)
|
||||
if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
|
||||
return ErrUintRange
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
*b = Uint(u64)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the hex encoding of b.
|
||||
func (b Uint) String() string {
|
||||
return EncodeUint64(uint64(b))
|
||||
}
|
||||
|
||||
func isString(input []byte) bool {
|
||||
return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
|
||||
}
|
||||
|
||||
func bytesHave0xPrefix(input []byte) bool {
|
||||
return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
|
||||
}
|
||||
|
||||
func checkText(input []byte, wantPrefix bool) ([]byte, error) {
|
||||
if len(input) == 0 {
|
||||
return nil, nil // empty strings are allowed
|
||||
}
|
||||
if bytesHave0xPrefix(input) {
|
||||
input = input[2:]
|
||||
} else if wantPrefix {
|
||||
return nil, ErrMissingPrefix
|
||||
}
|
||||
if len(input)%2 != 0 {
|
||||
return nil, ErrOddLength
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func checkNumberText(input []byte) (raw []byte, err error) {
|
||||
if len(input) == 0 {
|
||||
return nil, nil // empty strings are allowed
|
||||
}
|
||||
if !bytesHave0xPrefix(input) {
|
||||
return nil, ErrMissingPrefix
|
||||
}
|
||||
input = input[2:]
|
||||
if len(input) == 0 {
|
||||
return nil, ErrEmptyNumber
|
||||
}
|
||||
if len(input) > 1 && input[0] == '0' {
|
||||
return nil, ErrLeadingZero
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func wrapTypeError(err error, typ reflect.Type) error {
|
||||
if _, ok := err.(*decError); ok {
|
||||
return &json.UnmarshalTypeError{Value: err.Error(), Type: typ}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func errNonString(typ reflect.Type) error {
|
||||
return &json.UnmarshalTypeError{Value: "non-string", Type: typ}
|
||||
}
|
||||
|
||||
// bytesHaveXDCPrefix returns true if input starts with 'xdc' or 'XDC'
|
||||
func bytesHaveXDCPrefix(input []byte) bool {
|
||||
return len(input) >= 3 && (input[0] == 'x' || input[0] == 'X') &&
|
||||
(input[1] == 'd' || input[1] == 'D') && (input[2] == 'c' || input[2] == 'C')
|
||||
}
|
||||
|
|
@ -166,6 +166,51 @@ type Decoder interface {
|
|||
Time() time.Time
|
||||
}
|
||||
|
||||
// eth62 handlers - XDC compatible (basic messages only)
|
||||
var eth62 = map[uint64]msgHandler{
|
||||
NewBlockHashesMsg: handleNewBlockhashes,
|
||||
NewBlockMsg: handleNewBlock,
|
||||
TransactionsMsg: handleTransactions,
|
||||
GetBlockHeadersMsg: handleGetBlockHeaders,
|
||||
BlockHeadersMsg: handleBlockHeaders,
|
||||
GetBlockBodiesMsg: handleGetBlockBodies,
|
||||
BlockBodiesMsg: handleBlockBodies,
|
||||
}
|
||||
|
||||
// eth63 handlers - XDC compatible (adds state sync)
|
||||
var eth63 = map[uint64]msgHandler{
|
||||
NewBlockHashesMsg: handleNewBlockhashes,
|
||||
NewBlockMsg: handleNewBlock,
|
||||
TransactionsMsg: handleTransactions,
|
||||
GetBlockHeadersMsg: handleGetBlockHeaders,
|
||||
BlockHeadersMsg: handleBlockHeaders,
|
||||
GetBlockBodiesMsg: handleGetBlockBodies,
|
||||
BlockBodiesMsg: handleBlockBodies,
|
||||
GetNodeDataMsg: handleGetNodeData,
|
||||
NodeDataMsg: handleNodeData,
|
||||
GetReceiptsMsg: handleGetReceipts68,
|
||||
ReceiptsMsg: handleReceipts[*ReceiptList68],
|
||||
}
|
||||
|
||||
// xdpos2 handlers - XDC consensus protocol
|
||||
var xdpos2 = map[uint64]msgHandler{
|
||||
NewBlockHashesMsg: handleNewBlockhashes,
|
||||
NewBlockMsg: handleNewBlock,
|
||||
TransactionsMsg: handleTransactions,
|
||||
GetBlockHeadersMsg: handleGetBlockHeaders,
|
||||
BlockHeadersMsg: handleBlockHeaders,
|
||||
GetBlockBodiesMsg: handleGetBlockBodies,
|
||||
BlockBodiesMsg: handleBlockBodies,
|
||||
GetNodeDataMsg: handleGetNodeData,
|
||||
NodeDataMsg: handleNodeData,
|
||||
GetReceiptsMsg: handleGetReceipts68,
|
||||
ReceiptsMsg: handleReceipts[*ReceiptList68],
|
||||
// XDPoS2 consensus messages - to be implemented
|
||||
VoteMsg: handleVoteMsg,
|
||||
TimeoutMsg: handleTimeoutMsg,
|
||||
SyncInfoMsg: handleSyncInfoMsg,
|
||||
}
|
||||
|
||||
var eth68 = map[uint64]msgHandler{
|
||||
NewBlockHashesMsg: handleNewBlockhashes,
|
||||
NewBlockMsg: handleNewBlock,
|
||||
|
|
@ -209,11 +254,18 @@ func handleMessage(backend Backend, peer *Peer) error {
|
|||
defer msg.Discard()
|
||||
|
||||
var handlers map[uint64]msgHandler
|
||||
if peer.version == ETH68 {
|
||||
switch peer.version {
|
||||
case ETH62:
|
||||
handlers = eth62
|
||||
case ETH63:
|
||||
handlers = eth63
|
||||
case ETH68:
|
||||
handlers = eth68
|
||||
} else if peer.version == ETH69 {
|
||||
case ETH69:
|
||||
handlers = eth69
|
||||
} else {
|
||||
case XDPOS2:
|
||||
handlers = xdpos2
|
||||
default:
|
||||
return fmt.Errorf("unknown eth protocol version: %v", peer.version)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -552,3 +552,55 @@ func handleBlockRangeUpdate(backend Backend, msg Decoder, peer *Peer) error {
|
|||
peer.lastRange.Store(&update)
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleGetNodeData handles eth/63 GetNodeData messages (state trie nodes)
|
||||
func handleGetNodeData(backend Backend, msg Decoder, peer *Peer) error {
|
||||
// Decode the request
|
||||
var hashes []common.Hash
|
||||
if err := msg.Decode(&hashes); err != nil {
|
||||
return fmt.Errorf("failed to decode GetNodeData: %v", err)
|
||||
}
|
||||
// For now, return empty response - full implementation needs state trie access
|
||||
return peer.SendNodeData([][]byte{})
|
||||
}
|
||||
|
||||
// handleNodeData handles eth/63 NodeData response messages
|
||||
func handleNodeData(backend Backend, msg Decoder, peer *Peer) error {
|
||||
// Decode the response
|
||||
var data [][]byte
|
||||
if err := msg.Decode(&data); err != nil {
|
||||
return fmt.Errorf("failed to decode NodeData: %v", err)
|
||||
}
|
||||
// Process node data through the downloader
|
||||
return backend.Handle(peer, &NodeDataPacket{Data: data})
|
||||
}
|
||||
|
||||
// XDPoS2 consensus message handlers
|
||||
|
||||
// handleVoteMsg handles XDPoS2 vote messages
|
||||
func handleVoteMsg(backend Backend, msg Decoder, peer *Peer) error {
|
||||
// Decode and forward to consensus engine
|
||||
var vote []byte
|
||||
if err := msg.Decode(&vote); err != nil {
|
||||
return fmt.Errorf("failed to decode VoteMsg: %v", err)
|
||||
}
|
||||
return backend.Handle(peer, &VotePacket{Vote: vote})
|
||||
}
|
||||
|
||||
// handleTimeoutMsg handles XDPoS2 timeout messages
|
||||
func handleTimeoutMsg(backend Backend, msg Decoder, peer *Peer) error {
|
||||
var timeout []byte
|
||||
if err := msg.Decode(&timeout); err != nil {
|
||||
return fmt.Errorf("failed to decode TimeoutMsg: %v", err)
|
||||
}
|
||||
return backend.Handle(peer, &TimeoutPacket{Timeout: timeout})
|
||||
}
|
||||
|
||||
// handleSyncInfoMsg handles XDPoS2 sync info messages
|
||||
func handleSyncInfoMsg(backend Backend, msg Decoder, peer *Peer) error {
|
||||
var syncInfo []byte
|
||||
if err := msg.Decode(&syncInfo); err != nil {
|
||||
return fmt.Errorf("failed to decode SyncInfoMsg: %v", err)
|
||||
}
|
||||
return backend.Handle(peer, &SyncInfoPacket{SyncInfo: syncInfo})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -359,6 +359,11 @@ func (p *Peer) SendBlockRangeUpdate(msg BlockRangeUpdatePacket) error {
|
|||
return p2p.Send(p.rw, BlockRangeUpdateMsg, &msg)
|
||||
}
|
||||
|
||||
// SendNodeData sends a batch of state trie nodes to the peer (eth/63).
|
||||
func (p *Peer) SendNodeData(data [][]byte) error {
|
||||
return p2p.Send(p.rw, NodeDataMsg, data)
|
||||
}
|
||||
|
||||
// knownCache is a cache for known hashes.
|
||||
type knownCache struct {
|
||||
hashes mapset.Set[common.Hash]
|
||||
|
|
|
|||
|
|
@ -30,8 +30,11 @@ import (
|
|||
|
||||
// Constants to match up protocol versions and messages
|
||||
const (
|
||||
ETH68 = 68
|
||||
ETH69 = 69
|
||||
ETH62 = 62 // XDC compatible
|
||||
ETH63 = 63 // XDC compatible
|
||||
ETH68 = 68
|
||||
ETH69 = 69
|
||||
XDPOS2 = 100 // XDC custom protocol
|
||||
)
|
||||
|
||||
// ProtocolName is the official short name of the `eth` protocol used during
|
||||
|
|
@ -39,31 +42,55 @@ const (
|
|||
const ProtocolName = "eth"
|
||||
|
||||
// ProtocolVersions are the supported versions of the `eth` protocol (first
|
||||
// is primary).
|
||||
var ProtocolVersions = []uint{ETH69, ETH68}
|
||||
// is primary). XDC uses eth/62, eth/63, and xdpos2/100.
|
||||
var ProtocolVersions = []uint{XDPOS2, ETH63, ETH62, ETH69, ETH68}
|
||||
|
||||
// protocolLengths are the number of implemented message corresponding to
|
||||
// different protocol versions.
|
||||
var protocolLengths = map[uint]uint64{ETH68: 17, ETH69: 18}
|
||||
var protocolLengths = map[uint]uint64{
|
||||
ETH62: 8, // eth/62: basic messages
|
||||
ETH63: 17, // eth/63: adds state sync messages
|
||||
ETH68: 17, // eth/68: modern ethereum
|
||||
ETH69: 18, // eth/69: latest ethereum
|
||||
XDPOS2: 227, // xdpos2: XDC consensus messages
|
||||
}
|
||||
|
||||
// maxMessageSize is the maximum cap on the size of a protocol message.
|
||||
const maxMessageSize = 10 * 1024 * 1024
|
||||
|
||||
const (
|
||||
StatusMsg = 0x00
|
||||
NewBlockHashesMsg = 0x01
|
||||
TransactionsMsg = 0x02
|
||||
GetBlockHeadersMsg = 0x03
|
||||
BlockHeadersMsg = 0x04
|
||||
GetBlockBodiesMsg = 0x05
|
||||
BlockBodiesMsg = 0x06
|
||||
NewBlockMsg = 0x07
|
||||
NewPooledTransactionHashesMsg = 0x08
|
||||
GetPooledTransactionsMsg = 0x09
|
||||
// Protocol messages belonging to eth/62
|
||||
StatusMsg = 0x00
|
||||
NewBlockHashesMsg = 0x01
|
||||
TransactionsMsg = 0x02
|
||||
GetBlockHeadersMsg = 0x03
|
||||
BlockHeadersMsg = 0x04
|
||||
GetBlockBodiesMsg = 0x05
|
||||
BlockBodiesMsg = 0x06
|
||||
NewBlockMsg = 0x07
|
||||
|
||||
// XDC-specific messages (eth/62 extended)
|
||||
OrderTxMsg = 0x08 // XDC order transactions
|
||||
LendingTxMsg = 0x09 // XDC lending transactions
|
||||
|
||||
// eth/68+ messages (pooled transactions)
|
||||
NewPooledTransactionHashesMsg = 0x08 // Same as OrderTxMsg - version dependent
|
||||
GetPooledTransactionsMsg = 0x09 // Same as LendingTxMsg - version dependent
|
||||
PooledTransactionsMsg = 0x0a
|
||||
GetReceiptsMsg = 0x0f
|
||||
ReceiptsMsg = 0x10
|
||||
BlockRangeUpdateMsg = 0x11
|
||||
|
||||
// Protocol messages belonging to eth/63
|
||||
GetNodeDataMsg = 0x0d
|
||||
NodeDataMsg = 0x0e
|
||||
GetReceiptsMsg = 0x0f
|
||||
ReceiptsMsg = 0x10
|
||||
|
||||
// eth/69 messages
|
||||
BlockRangeUpdateMsg = 0x11
|
||||
|
||||
// XDPoS2 consensus messages (xdpos2/100)
|
||||
VoteMsg = 0xe0
|
||||
TimeoutMsg = 0xe1
|
||||
SyncInfoMsg = 0xe2
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -381,3 +408,33 @@ func (*ReceiptsRLPResponse) Kind() byte { return ReceiptsMsg }
|
|||
|
||||
func (*BlockRangeUpdatePacket) Name() string { return "BlockRangeUpdate" }
|
||||
func (*BlockRangeUpdatePacket) Kind() byte { return BlockRangeUpdateMsg }
|
||||
|
||||
// eth/63 NodeData packets
|
||||
type NodeDataPacket struct {
|
||||
Data [][]byte
|
||||
}
|
||||
|
||||
func (*NodeDataPacket) Name() string { return "NodeData" }
|
||||
func (*NodeDataPacket) Kind() byte { return NodeDataMsg }
|
||||
|
||||
// XDPoS2 consensus packets
|
||||
type VotePacket struct {
|
||||
Vote []byte
|
||||
}
|
||||
|
||||
func (*VotePacket) Name() string { return "Vote" }
|
||||
func (*VotePacket) Kind() byte { return VoteMsg }
|
||||
|
||||
type TimeoutPacket struct {
|
||||
Timeout []byte
|
||||
}
|
||||
|
||||
func (*TimeoutPacket) Name() string { return "Timeout" }
|
||||
func (*TimeoutPacket) Kind() byte { return TimeoutMsg }
|
||||
|
||||
type SyncInfoPacket struct {
|
||||
SyncInfo []byte
|
||||
}
|
||||
|
||||
func (*SyncInfoPacket) Name() string { return "SyncInfo" }
|
||||
func (*SyncInfoPacket) Kind() byte { return SyncInfoMsg }
|
||||
|
|
|
|||
383
eth/protocols/eth/protocol.go.bak
Normal file
383
eth/protocols/eth/protocol.go.bak
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
// Copyright 2020 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package eth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/forkid"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
// Constants to match up protocol versions and messages
|
||||
const (
|
||||
ETH68 = 68
|
||||
ETH69 = 69
|
||||
)
|
||||
|
||||
// ProtocolName is the official short name of the `eth` protocol used during
|
||||
// devp2p capability negotiation.
|
||||
const ProtocolName = "eth"
|
||||
|
||||
// ProtocolVersions are the supported versions of the `eth` protocol (first
|
||||
// is primary).
|
||||
var ProtocolVersions = []uint{ETH69, ETH68}
|
||||
|
||||
// protocolLengths are the number of implemented message corresponding to
|
||||
// different protocol versions.
|
||||
var protocolLengths = map[uint]uint64{ETH68: 17, ETH69: 18}
|
||||
|
||||
// maxMessageSize is the maximum cap on the size of a protocol message.
|
||||
const maxMessageSize = 10 * 1024 * 1024
|
||||
|
||||
const (
|
||||
StatusMsg = 0x00
|
||||
NewBlockHashesMsg = 0x01
|
||||
TransactionsMsg = 0x02
|
||||
GetBlockHeadersMsg = 0x03
|
||||
BlockHeadersMsg = 0x04
|
||||
GetBlockBodiesMsg = 0x05
|
||||
BlockBodiesMsg = 0x06
|
||||
NewBlockMsg = 0x07
|
||||
NewPooledTransactionHashesMsg = 0x08
|
||||
GetPooledTransactionsMsg = 0x09
|
||||
PooledTransactionsMsg = 0x0a
|
||||
GetReceiptsMsg = 0x0f
|
||||
ReceiptsMsg = 0x10
|
||||
BlockRangeUpdateMsg = 0x11
|
||||
)
|
||||
|
||||
var (
|
||||
errMsgTooLarge = errors.New("message too long")
|
||||
errInvalidMsgCode = errors.New("invalid message code")
|
||||
errProtocolVersionMismatch = errors.New("protocol version mismatch")
|
||||
// handshake errors
|
||||
errNoStatusMsg = errors.New("no status message")
|
||||
errNetworkIDMismatch = errors.New("network ID mismatch")
|
||||
errGenesisMismatch = errors.New("genesis mismatch")
|
||||
errForkIDRejected = errors.New("fork ID rejected")
|
||||
errInvalidBlockRange = errors.New("invalid block range in status")
|
||||
)
|
||||
|
||||
// Packet represents a p2p message in the `eth` protocol.
|
||||
type Packet interface {
|
||||
Name() string // Name returns a string corresponding to the message type.
|
||||
Kind() byte // Kind returns the message type.
|
||||
}
|
||||
|
||||
// StatusPacket is the network packet for the status message.
|
||||
type StatusPacket68 struct {
|
||||
ProtocolVersion uint32
|
||||
NetworkID uint64
|
||||
TD *big.Int
|
||||
Head common.Hash
|
||||
Genesis common.Hash
|
||||
ForkID forkid.ID
|
||||
}
|
||||
|
||||
// StatusPacket69 is the network packet for the status message.
|
||||
type StatusPacket69 struct {
|
||||
ProtocolVersion uint32
|
||||
NetworkID uint64
|
||||
Genesis common.Hash
|
||||
ForkID forkid.ID
|
||||
// initial available block range
|
||||
EarliestBlock uint64
|
||||
LatestBlock uint64
|
||||
LatestBlockHash common.Hash
|
||||
}
|
||||
|
||||
// NewBlockHashesPacket is the network packet for the block announcements.
|
||||
type NewBlockHashesPacket []struct {
|
||||
Hash common.Hash // Hash of one particular block being announced
|
||||
Number uint64 // Number of one particular block being announced
|
||||
}
|
||||
|
||||
// Unpack retrieves the block hashes and numbers from the announcement packet
|
||||
// and returns them in a split flat format that's more consistent with the
|
||||
// internal data structures.
|
||||
func (p *NewBlockHashesPacket) Unpack() ([]common.Hash, []uint64) {
|
||||
var (
|
||||
hashes = make([]common.Hash, len(*p))
|
||||
numbers = make([]uint64, len(*p))
|
||||
)
|
||||
for i, body := range *p {
|
||||
hashes[i], numbers[i] = body.Hash, body.Number
|
||||
}
|
||||
return hashes, numbers
|
||||
}
|
||||
|
||||
// TransactionsPacket is the network packet for broadcasting new transactions.
|
||||
type TransactionsPacket []*types.Transaction
|
||||
|
||||
// GetBlockHeadersRequest represents a block header query.
|
||||
type GetBlockHeadersRequest struct {
|
||||
Origin HashOrNumber // Block from which to retrieve headers
|
||||
Amount uint64 // Maximum number of headers to retrieve
|
||||
Skip uint64 // Blocks to skip between consecutive headers
|
||||
Reverse bool // Query direction (false = rising towards latest, true = falling towards genesis)
|
||||
}
|
||||
|
||||
// GetBlockHeadersPacket represents a block header query with request ID wrapping.
|
||||
type GetBlockHeadersPacket struct {
|
||||
RequestId uint64
|
||||
*GetBlockHeadersRequest
|
||||
}
|
||||
|
||||
// HashOrNumber is a combined field for specifying an origin block.
|
||||
type HashOrNumber struct {
|
||||
Hash common.Hash // Block hash from which to retrieve headers (excludes Number)
|
||||
Number uint64 // Block hash from which to retrieve headers (excludes Hash)
|
||||
}
|
||||
|
||||
// EncodeRLP is a specialized encoder for HashOrNumber to encode only one of the
|
||||
// two contained union fields.
|
||||
func (hn *HashOrNumber) EncodeRLP(w io.Writer) error {
|
||||
if hn.Hash == (common.Hash{}) {
|
||||
return rlp.Encode(w, hn.Number)
|
||||
}
|
||||
if hn.Number != 0 {
|
||||
return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
|
||||
}
|
||||
return rlp.Encode(w, hn.Hash)
|
||||
}
|
||||
|
||||
// DecodeRLP is a specialized decoder for HashOrNumber to decode the contents
|
||||
// into either a block hash or a block number.
|
||||
func (hn *HashOrNumber) DecodeRLP(s *rlp.Stream) error {
|
||||
_, size, err := s.Kind()
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case size == 32:
|
||||
hn.Number = 0
|
||||
return s.Decode(&hn.Hash)
|
||||
case size <= 8:
|
||||
hn.Hash = common.Hash{}
|
||||
return s.Decode(&hn.Number)
|
||||
default:
|
||||
return fmt.Errorf("invalid input size %d for origin", size)
|
||||
}
|
||||
}
|
||||
|
||||
// BlockHeadersRequest represents a block header response.
|
||||
type BlockHeadersRequest []*types.Header
|
||||
|
||||
// BlockHeadersPacket represents a block header response over with request ID wrapping.
|
||||
type BlockHeadersPacket struct {
|
||||
RequestId uint64
|
||||
BlockHeadersRequest
|
||||
}
|
||||
|
||||
// BlockHeadersRLPResponse represents a block header response, to use when we already
|
||||
// have the headers rlp encoded.
|
||||
type BlockHeadersRLPResponse []rlp.RawValue
|
||||
|
||||
// BlockHeadersRLPPacket represents a block header response with request ID wrapping.
|
||||
type BlockHeadersRLPPacket struct {
|
||||
RequestId uint64
|
||||
BlockHeadersRLPResponse
|
||||
}
|
||||
|
||||
// NewBlockPacket is the network packet for the block propagation message.
|
||||
type NewBlockPacket struct {
|
||||
Block *types.Block
|
||||
TD *big.Int
|
||||
}
|
||||
|
||||
// GetBlockBodiesRequest represents a block body query.
|
||||
type GetBlockBodiesRequest []common.Hash
|
||||
|
||||
// GetBlockBodiesPacket represents a block body query with request ID wrapping.
|
||||
type GetBlockBodiesPacket struct {
|
||||
RequestId uint64
|
||||
GetBlockBodiesRequest
|
||||
}
|
||||
|
||||
// BlockBodiesResponse is the network packet for block content distribution.
|
||||
type BlockBodiesResponse []*BlockBody
|
||||
|
||||
// BlockBodiesPacket is the network packet for block content distribution with
|
||||
// request ID wrapping.
|
||||
type BlockBodiesPacket struct {
|
||||
RequestId uint64
|
||||
BlockBodiesResponse
|
||||
}
|
||||
|
||||
// BlockBodiesRLPResponse is used for replying to block body requests, in cases
|
||||
// where we already have them RLP-encoded, and thus can avoid the decode-encode
|
||||
// roundtrip.
|
||||
type BlockBodiesRLPResponse []rlp.RawValue
|
||||
|
||||
// BlockBodiesRLPPacket is the BlockBodiesRLPResponse with request ID wrapping.
|
||||
type BlockBodiesRLPPacket struct {
|
||||
RequestId uint64
|
||||
BlockBodiesRLPResponse
|
||||
}
|
||||
|
||||
// BlockBody represents the data content of a single block.
|
||||
type BlockBody struct {
|
||||
Transactions []*types.Transaction // Transactions contained within a block
|
||||
Uncles []*types.Header // Uncles contained within a block
|
||||
Withdrawals []*types.Withdrawal `rlp:"optional"` // Withdrawals contained within a block
|
||||
}
|
||||
|
||||
// Unpack retrieves the transactions and uncles from the range packet and returns
|
||||
// them in a split flat format that's more consistent with the internal data structures.
|
||||
func (p *BlockBodiesResponse) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal) {
|
||||
var (
|
||||
txset = make([][]*types.Transaction, len(*p))
|
||||
uncleset = make([][]*types.Header, len(*p))
|
||||
withdrawalset = make([][]*types.Withdrawal, len(*p))
|
||||
)
|
||||
for i, body := range *p {
|
||||
txset[i], uncleset[i], withdrawalset[i] = body.Transactions, body.Uncles, body.Withdrawals
|
||||
}
|
||||
return txset, uncleset, withdrawalset
|
||||
}
|
||||
|
||||
// GetReceiptsRequest represents a block receipts query.
|
||||
type GetReceiptsRequest []common.Hash
|
||||
|
||||
// GetReceiptsPacket represents a block receipts query with request ID wrapping.
|
||||
type GetReceiptsPacket struct {
|
||||
RequestId uint64
|
||||
GetReceiptsRequest
|
||||
}
|
||||
|
||||
// ReceiptsResponse is the network packet for block receipts distribution.
|
||||
type ReceiptsResponse []types.Receipts
|
||||
|
||||
// ReceiptsList is a type constraint for block receceipt list types.
|
||||
type ReceiptsList interface {
|
||||
*ReceiptList68 | *ReceiptList69
|
||||
setBuffers(*receiptListBuffers)
|
||||
EncodeForStorage() rlp.RawValue
|
||||
types.DerivableList
|
||||
}
|
||||
|
||||
// ReceiptsPacket is the network packet for block receipts distribution with
|
||||
// request ID wrapping.
|
||||
type ReceiptsPacket[L ReceiptsList] struct {
|
||||
RequestId uint64
|
||||
List []L
|
||||
}
|
||||
|
||||
// ReceiptsRLPResponse is used for receipts, when we already have it encoded
|
||||
type ReceiptsRLPResponse []rlp.RawValue
|
||||
|
||||
// ReceiptsRLPPacket is ReceiptsRLPResponse with request ID wrapping.
|
||||
type ReceiptsRLPPacket struct {
|
||||
RequestId uint64
|
||||
ReceiptsRLPResponse
|
||||
}
|
||||
|
||||
// NewPooledTransactionHashesPacket represents a transaction announcement packet on eth/68 and newer.
|
||||
type NewPooledTransactionHashesPacket struct {
|
||||
Types []byte
|
||||
Sizes []uint32
|
||||
Hashes []common.Hash
|
||||
}
|
||||
|
||||
// GetPooledTransactionsRequest represents a transaction query.
|
||||
type GetPooledTransactionsRequest []common.Hash
|
||||
|
||||
// GetPooledTransactionsPacket represents a transaction query with request ID wrapping.
|
||||
type GetPooledTransactionsPacket struct {
|
||||
RequestId uint64
|
||||
GetPooledTransactionsRequest
|
||||
}
|
||||
|
||||
// PooledTransactionsResponse is the network packet for transaction distribution.
|
||||
type PooledTransactionsResponse []*types.Transaction
|
||||
|
||||
// PooledTransactionsPacket is the network packet for transaction distribution
|
||||
// with request ID wrapping.
|
||||
type PooledTransactionsPacket struct {
|
||||
RequestId uint64
|
||||
PooledTransactionsResponse
|
||||
}
|
||||
|
||||
// PooledTransactionsRLPResponse is the network packet for transaction distribution, used
|
||||
// in the cases we already have them in rlp-encoded form
|
||||
type PooledTransactionsRLPResponse []rlp.RawValue
|
||||
|
||||
// PooledTransactionsRLPPacket is PooledTransactionsRLPResponse with request ID wrapping.
|
||||
type PooledTransactionsRLPPacket struct {
|
||||
RequestId uint64
|
||||
PooledTransactionsRLPResponse
|
||||
}
|
||||
|
||||
// BlockRangeUpdatePacket is an announcement of the node's available block range.
|
||||
type BlockRangeUpdatePacket struct {
|
||||
EarliestBlock uint64
|
||||
LatestBlock uint64
|
||||
LatestBlockHash common.Hash
|
||||
}
|
||||
|
||||
func (*StatusPacket68) Name() string { return "Status" }
|
||||
func (*StatusPacket68) Kind() byte { return StatusMsg }
|
||||
|
||||
func (*StatusPacket69) Name() string { return "Status" }
|
||||
func (*StatusPacket69) Kind() byte { return StatusMsg }
|
||||
|
||||
func (*NewBlockHashesPacket) Name() string { return "NewBlockHashes" }
|
||||
func (*NewBlockHashesPacket) Kind() byte { return NewBlockHashesMsg }
|
||||
|
||||
func (*TransactionsPacket) Name() string { return "Transactions" }
|
||||
func (*TransactionsPacket) Kind() byte { return TransactionsMsg }
|
||||
|
||||
func (*GetBlockHeadersRequest) Name() string { return "GetBlockHeaders" }
|
||||
func (*GetBlockHeadersRequest) Kind() byte { return GetBlockHeadersMsg }
|
||||
|
||||
func (*BlockHeadersRequest) Name() string { return "BlockHeaders" }
|
||||
func (*BlockHeadersRequest) Kind() byte { return BlockHeadersMsg }
|
||||
|
||||
func (*GetBlockBodiesRequest) Name() string { return "GetBlockBodies" }
|
||||
func (*GetBlockBodiesRequest) Kind() byte { return GetBlockBodiesMsg }
|
||||
|
||||
func (*BlockBodiesResponse) Name() string { return "BlockBodies" }
|
||||
func (*BlockBodiesResponse) Kind() byte { return BlockBodiesMsg }
|
||||
|
||||
func (*NewBlockPacket) Name() string { return "NewBlock" }
|
||||
func (*NewBlockPacket) Kind() byte { return NewBlockMsg }
|
||||
|
||||
func (*NewPooledTransactionHashesPacket) Name() string { return "NewPooledTransactionHashes" }
|
||||
func (*NewPooledTransactionHashesPacket) Kind() byte { return NewPooledTransactionHashesMsg }
|
||||
|
||||
func (*GetPooledTransactionsRequest) Name() string { return "GetPooledTransactions" }
|
||||
func (*GetPooledTransactionsRequest) Kind() byte { return GetPooledTransactionsMsg }
|
||||
|
||||
func (*PooledTransactionsResponse) Name() string { return "PooledTransactions" }
|
||||
func (*PooledTransactionsResponse) Kind() byte { return PooledTransactionsMsg }
|
||||
|
||||
func (*GetReceiptsRequest) Name() string { return "GetReceipts" }
|
||||
func (*GetReceiptsRequest) Kind() byte { return GetReceiptsMsg }
|
||||
|
||||
func (*ReceiptsResponse) Name() string { return "Receipts" }
|
||||
func (*ReceiptsResponse) Kind() byte { return ReceiptsMsg }
|
||||
|
||||
func (*ReceiptsRLPResponse) Name() string { return "Receipts" }
|
||||
func (*ReceiptsRLPResponse) Kind() byte { return ReceiptsMsg }
|
||||
|
||||
func (*BlockRangeUpdatePacket) Name() string { return "BlockRangeUpdate" }
|
||||
func (*BlockRangeUpdatePacket) Kind() byte { return BlockRangeUpdateMsg }
|
||||
113
genesis/xdc_mainnet_fixed.json
Normal file
113
genesis/xdc_mainnet_fixed.json
Normal file
File diff suppressed because one or more lines are too long
113
genesis/xdc_mainnet_official.json
Normal file
113
genesis/xdc_mainnet_official.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue