123 lines
3.6 KiB
Go
123 lines
3.6 KiB
Go
|
// 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 diff
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
|
||
|
"golang.org/x/crypto/sha3"
|
||
|
|
||
|
"github.com/ethereum/go-ethereum/common"
|
||
|
"github.com/ethereum/go-ethereum/core/types"
|
||
|
"github.com/ethereum/go-ethereum/rlp"
|
||
|
)
|
||
|
|
||
|
// Constants to match up protocol versions and messages
|
||
|
const (
|
||
|
Diff1 = 1
|
||
|
)
|
||
|
|
||
|
// ProtocolName is the official short name of the `diff` protocol used during
|
||
|
// devp2p capability negotiation.
|
||
|
const ProtocolName = "diff"
|
||
|
|
||
|
// ProtocolVersions are the supported versions of the `diff` protocol (first
|
||
|
// is primary).
|
||
|
var ProtocolVersions = []uint{Diff1}
|
||
|
|
||
|
// protocolLengths are the number of implemented message corresponding to
|
||
|
// different protocol versions.
|
||
|
var protocolLengths = map[uint]uint64{Diff1: 4}
|
||
|
|
||
|
// maxMessageSize is the maximum cap on the size of a protocol message.
|
||
|
const maxMessageSize = 10 * 1024 * 1024
|
||
|
|
||
|
const (
|
||
|
DiffCapMsg = 0x00
|
||
|
GetDiffLayerMsg = 0x01
|
||
|
DiffLayerMsg = 0x02
|
||
|
FullDiffLayerMsg = 0x03
|
||
|
)
|
||
|
|
||
|
var defaultExtra = []byte{0x00}
|
||
|
|
||
|
var (
|
||
|
errMsgTooLarge = errors.New("message too long")
|
||
|
errDecode = errors.New("invalid message")
|
||
|
errInvalidMsgCode = errors.New("invalid message code")
|
||
|
errUnexpectedMsg = errors.New("unexpected message code")
|
||
|
errNoCapMsg = errors.New("miss cap message during handshake")
|
||
|
)
|
||
|
|
||
|
// Packet represents a p2p message in the `diff` protocol.
|
||
|
type Packet interface {
|
||
|
Name() string // Name returns a string corresponding to the message type.
|
||
|
Kind() byte // Kind returns the message type.
|
||
|
}
|
||
|
|
||
|
type GetDiffLayersPacket struct {
|
||
|
RequestId uint64
|
||
|
BlockHashes []common.Hash
|
||
|
}
|
||
|
|
||
|
func (p *DiffLayersPacket) Unpack() ([]*types.DiffLayer, error) {
|
||
|
diffLayers := make([]*types.DiffLayer, 0, len(*p))
|
||
|
hasher := sha3.NewLegacyKeccak256()
|
||
|
for _, rawData := range *p {
|
||
|
var diff types.DiffLayer
|
||
|
err := rlp.DecodeBytes(rawData, &diff)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("%w: diff layer %v", errDecode, err)
|
||
|
}
|
||
|
diffLayers = append(diffLayers, &diff)
|
||
|
_, err = hasher.Write(rawData)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
var diffHash common.Hash
|
||
|
hasher.Sum(diffHash[:0])
|
||
|
hasher.Reset()
|
||
|
diff.DiffHash = diffHash
|
||
|
}
|
||
|
return diffLayers, nil
|
||
|
}
|
||
|
|
||
|
type DiffCapPacket struct {
|
||
|
DiffSync bool
|
||
|
Extra rlp.RawValue // for extension
|
||
|
}
|
||
|
|
||
|
type DiffLayersPacket []rlp.RawValue
|
||
|
|
||
|
type FullDiffLayersPacket struct {
|
||
|
RequestId uint64
|
||
|
DiffLayersPacket
|
||
|
}
|
||
|
|
||
|
func (*GetDiffLayersPacket) Name() string { return "GetDiffLayers" }
|
||
|
func (*GetDiffLayersPacket) Kind() byte { return GetDiffLayerMsg }
|
||
|
|
||
|
func (*DiffLayersPacket) Name() string { return "DiffLayers" }
|
||
|
func (*DiffLayersPacket) Kind() byte { return DiffLayerMsg }
|
||
|
|
||
|
func (*FullDiffLayersPacket) Name() string { return "FullDiffLayers" }
|
||
|
func (*FullDiffLayersPacket) Kind() byte { return FullDiffLayerMsg }
|
||
|
|
||
|
func (*DiffCapPacket) Name() string { return "DiffCap" }
|
||
|
func (*DiffCapPacket) Kind() byte { return DiffCapMsg }
|