aboutsummaryrefslogblamecommitdiffstats
path: root/dex/protocol.go
blob: e09829cc895c7cf7eb91ede1163eb4e5278e6674 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                                    
  
                                                                        



                                                                               
                                                                         




                                                                           
                                                      

                                  















                                                                                  
           

        
                      

             
 


                                                      
                                                 

                                                     
                                  



                                                       
                  


                                                                                              
                        

                                                                                     
                                    

                                                                                                      
                                  



















                                                                                            

                                                
                        
 
                                     




                                     

                                     
                                     
 

                             















                                  




                                





























                                                                        
                           
                                     
 


                         
 
                                                      
 
                                                   

 




                                                                      


                          

                                         


                                     

 



                                                           
                              















                                                                                                               

                    
                     





































                                                                                                       





                                                                     


                                                                        

 









                                






                                                                                  



                             






                                             
// Copyright 2018 The dexon-consensus Authors
// This file is part of the dexon-consensus library.
//
// The dexon-consensus 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 dexon-consensus 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 dexon-consensus library. If not, see
// <http://www.gnu.org/licenses/>.

// Copyright 2014 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 dex

import (
    "crypto/ecdsa"
    "fmt"
    "io"

    "github.com/dexon-foundation/dexon/common"
    "github.com/dexon-foundation/dexon/core"
    "github.com/dexon-foundation/dexon/core/types"
    "github.com/dexon-foundation/dexon/event"
    "github.com/dexon-foundation/dexon/p2p/enode"
    "github.com/dexon-foundation/dexon/rlp"
    "golang.org/x/crypto/sha3"
)

// Constants to match up protocol versions and messages
const (
    dex64 = 64
)

// ProtocolName is the official short name of the protocol used during capability negotiation.
var ProtocolName = "dex"

// ProtocolVersions are the upported versions of the eth protocol (first is primary).
var ProtocolVersions = []uint{dex64}

// ProtocolLengths are the number of implemented message corresponding to different protocol versions.
var ProtocolLengths = []uint64{43}

const ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message

// eth protocol message codes
const (
    // Protocol messages belonging to eth/62
    StatusMsg          = 0x00
    NewBlockHashesMsg  = 0x01
    TxMsg              = 0x02
    GetBlockHeadersMsg = 0x03
    BlockHeadersMsg    = 0x04
    GetBlockBodiesMsg  = 0x05
    BlockBodiesMsg     = 0x06
    NewBlockMsg        = 0x07

    // Protocol messages belonging to eth/63
    GetNodeDataMsg = 0x0d
    NodeDataMsg    = 0x0e
    GetReceiptsMsg = 0x0f
    ReceiptsMsg    = 0x10

    // Protocol messages belonging to dex/64
    RecordMsg = 0x11

    CoreBlockMsg           = 0x20
    VoteMsg                = 0x21
    AgreementMsg           = 0x22
    RandomnessMsg          = 0x23
    DKGPrivateShareMsg     = 0x24
    DKGPartialSignatureMsg = 0x25
    PullBlocksMsg          = 0x26
    PullVotesMsg           = 0x27
    PullRandomnessMsg      = 0x28

    GetGovStateMsg = 0x29
    GovStateMsg    = 0x2a
)

type errCode int

const (
    ErrMsgTooLarge = iota
    ErrDecode
    ErrInvalidMsgCode
    ErrProtocolVersionMismatch
    ErrNetworkIdMismatch
    ErrGenesisBlockMismatch
    ErrNoStatusMsg
    ErrExtraStatusMsg
    ErrSuspendedPeer
)

const (
    fetcherReq = uint8(iota)
    downloaderReq
)

func (e errCode) String() string {
    return errorToString[int(e)]
}

// XXX change once legacy code is out
var errorToString = map[int]string{
    ErrMsgTooLarge:             "Message too long",
    ErrDecode:                  "Invalid message",
    ErrInvalidMsgCode:          "Invalid message code",
    ErrProtocolVersionMismatch: "Protocol version mismatch",
    ErrNetworkIdMismatch:       "NetworkId mismatch",
    ErrGenesisBlockMismatch:    "Genesis block mismatch",
    ErrNoStatusMsg:             "No status message",
    ErrExtraStatusMsg:          "Extra status message",
    ErrSuspendedPeer:           "Suspended peer",
}

type txPool interface {
    // AddRemotes should add the given transactions to the pool.
    AddRemotes([]*types.Transaction) []error

    // Pending should return pending transactions.
    // The slice should be modifiable by the caller.
    Pending() (map[common.Address]types.Transactions, error)

    // SubscribeNewTxsEvent should return an event subscription of
    // NewTxsEvent and send events to the given channel.
    SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
}

type governance interface {
    GetRoundHeight(uint64) uint64

    Round() uint64

    CRSRound() uint64

    NotarySet(uint64) (map[string]struct{}, error)

    DKGSet(uint64) (map[string]struct{}, error)
}

type dexconApp interface {
    SubscribeNewFinalizedBlockEvent(
        chan<- core.NewFinalizedBlockEvent) event.Subscription
}

type p2pServer interface {
    Self() *enode.Node

    GetPrivateKey() *ecdsa.PrivateKey

    AddDirectPeer(*enode.Node)

    RemoveDirectPeer(*enode.Node)
}

// statusData is the network packet for the status message.
type statusData struct {
    ProtocolVersion uint32
    NetworkId       uint64
    Number          uint64
    CurrentBlock    common.Hash
    GenesisBlock    common.Hash
}

// newBlockHashesData is the network packet for the block announcements.
type newBlockHashesData []struct {
    Hash   common.Hash // Hash of one particular block being announced
    Number uint64      // Number of one particular block being announced
}

// getBlockHeadersData represents a block header query.
type getBlockHeadersData 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)

    WithGov bool
    Flag    uint8
}

// 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, _ := s.Kind()
    origin, err := s.Raw()
    if err == nil {
        switch {
        case size == 32:
            err = rlp.DecodeBytes(origin, &hn.Hash)
        case size <= 8:
            err = rlp.DecodeBytes(origin, &hn.Number)
        default:
            err = fmt.Errorf("invalid input size %d for origin", size)
        }
    }
    return err
}

// headersData is the network packet for header content distribution.
type headersData struct {
    Flag    uint8
    Headers []*types.HeaderWithGovState
}

// newBlockData is the network packet for the block propagation message.
type newBlockData struct {
    Block *types.Block
}

type getBlockBodiesData struct {
    Flag   uint8
    Hashes rlp.RawValue
}

type blockBodiesDataRLP struct {
    Flag   uint8
    Bodies []rlp.RawValue
}

// 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
}

// blockBodiesData is the network packet for block content distribution.
type blockBodiesData struct {
    Flag   uint8
    Bodies []*blockBody
}

func rlpHash(x interface{}) (h common.Hash) {
    hw := sha3.NewLegacyKeccak256()
    rlp.Encode(hw, x)
    hw.Sum(h[:0])
    return h
}