Fixed header sync issue (#17)

* headers can now sync till infinity

* fixed empty hashStop getBlock payload + test

* added more test + more binary decoding/encoding

* bump version
This commit is contained in:
Anthony De Meulemeester 2018-02-07 15:16:50 +01:00 committed by GitHub
parent 046494dd68
commit b6d8271b8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 290 additions and 106 deletions

View file

@ -1 +1 @@
0.7.0 0.8.0

View file

@ -36,16 +36,32 @@ type BlockBase struct {
// DecodeBinary implements the payload interface. // DecodeBinary implements the payload interface.
func (b *BlockBase) DecodeBinary(r io.Reader) error { func (b *BlockBase) DecodeBinary(r io.Reader) error {
binary.Read(r, binary.LittleEndian, &b.Version) if err := binary.Read(r, binary.LittleEndian, &b.Version); err != nil {
binary.Read(r, binary.LittleEndian, &b.PrevHash) return err
binary.Read(r, binary.LittleEndian, &b.MerkleRoot) }
binary.Read(r, binary.LittleEndian, &b.Timestamp) if err := binary.Read(r, binary.LittleEndian, &b.PrevHash); err != nil {
binary.Read(r, binary.LittleEndian, &b.Index) return err
binary.Read(r, binary.LittleEndian, &b.ConsensusData) }
binary.Read(r, binary.LittleEndian, &b.NextConsensus) if err := binary.Read(r, binary.LittleEndian, &b.MerkleRoot); err != nil {
return err
}
if err := binary.Read(r, binary.LittleEndian, &b.Timestamp); err != nil {
return err
}
if err := binary.Read(r, binary.LittleEndian, &b.Index); err != nil {
return err
}
if err := binary.Read(r, binary.LittleEndian, &b.ConsensusData); err != nil {
return err
}
if err := binary.Read(r, binary.LittleEndian, &b.NextConsensus); err != nil {
return err
}
var padding uint8 var padding uint8
binary.Read(r, binary.LittleEndian, &padding) if err := binary.Read(r, binary.LittleEndian, &padding); err != nil {
return err
}
if padding != 1 { if padding != 1 {
return fmt.Errorf("format error: padding must equal 1 got %d", padding) return fmt.Errorf("format error: padding must equal 1 got %d", padding)
} }
@ -86,6 +102,21 @@ func (b *BlockBase) encodeHashableFields(w io.Writer) error {
return err return err
} }
// EncodeBinary implements the Payload interface
func (b *BlockBase) EncodeBinary(w io.Writer) error {
if err := b.encodeHashableFields(w); err != nil {
return err
}
// padding
if err := binary.Write(w, binary.LittleEndian, uint8(1)); err != nil {
return err
}
// script
return b.Script.EncodeBinary(w)
}
// Header holds the head info of a block // Header holds the head info of a block
type Header struct { type Header struct {
BlockBase BlockBase
@ -115,7 +146,12 @@ func (h *Header) DecodeBinary(r io.Reader) error {
// EncodeBinary impelements the Payload interface. // EncodeBinary impelements the Payload interface.
func (h *Header) EncodeBinary(w io.Writer) error { func (h *Header) EncodeBinary(w io.Writer) error {
return nil if err := h.BlockBase.EncodeBinary(w); err != nil {
return err
}
// padding
return binary.Write(w, binary.LittleEndian, uint8(0))
} }
// Block represents one block in the chain. // Block represents one block in the chain.

View file

@ -82,7 +82,10 @@ func newBlockBase() BlockBase {
Index: 1, Index: 1,
ConsensusData: 1111, ConsensusData: 1111,
NextConsensus: util.Uint160{}, NextConsensus: util.Uint160{},
Script: &Witness{}, Script: &Witness{
VerificationScript: []byte{0x0},
InvocationScript: []byte{0x1},
},
} }
} }

View file

@ -191,6 +191,11 @@ func (bc *Blockchain) CurrentBlockHash() (hash util.Uint256) {
return bc.headerIndex[bc.currentBlockHeight] return bc.headerIndex[bc.currentBlockHeight]
} }
// CurrentHeaderHash returns the hash of the latest known header.
func (bc *Blockchain) CurrentHeaderHash() (hash util.Uint256) {
return bc.headerIndex[len(bc.headerIndex)-1]
}
// BlockHeight return the height/index of the latest block this node has. // BlockHeight return the height/index of the latest block this node has.
func (bc *Blockchain) BlockHeight() uint32 { func (bc *Blockchain) BlockHeight() uint32 {
return bc.currentBlockHeight return bc.currentBlockHeight

View file

@ -31,9 +31,9 @@ func TestAddHeaders(t *testing.T) {
startHash, _ := util.Uint256DecodeFromString("996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099") startHash, _ := util.Uint256DecodeFromString("996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099")
bc := NewBlockchain(NewMemoryStore(), log.New(os.Stdout, "", 0), startHash) bc := NewBlockchain(NewMemoryStore(), log.New(os.Stdout, "", 0), startHash)
h1 := &Header{BlockBase: BlockBase{Version: 0, Index: 1}} h1 := &Header{BlockBase: BlockBase{Version: 0, Index: 1, Script: &Witness{}}}
h2 := &Header{BlockBase: BlockBase{Version: 0, Index: 2}} h2 := &Header{BlockBase: BlockBase{Version: 0, Index: 2, Script: &Witness{}}}
h3 := &Header{BlockBase: BlockBase{Version: 0, Index: 3}} h3 := &Header{BlockBase: BlockBase{Version: 0, Index: 3, Script: &Witness{}}}
if err := bc.AddHeaders(h1, h2, h3); err != nil { if err := bc.AddHeaders(h1, h2, h3); err != nil {
t.Fatal(err) t.Fatal(err)

61
pkg/core/header_test.go Normal file
View file

@ -0,0 +1,61 @@
package core
import (
"bytes"
"crypto/sha256"
"testing"
"time"
"github.com/CityOfZion/neo-go/pkg/util"
)
func TestHeaderEncodeDecode(t *testing.T) {
header := Header{BlockBase: BlockBase{
Version: 0,
PrevHash: sha256.Sum256([]byte("prevhash")),
MerkleRoot: sha256.Sum256([]byte("merkleroot")),
Timestamp: uint32(time.Now().UTC().Unix()),
Index: 3445,
ConsensusData: 394949,
NextConsensus: util.Uint160{},
Script: &Witness{
InvocationScript: []byte{0x10},
VerificationScript: []byte{0x11},
},
}}
buf := new(bytes.Buffer)
if err := header.EncodeBinary(buf); err != nil {
t.Fatal(err)
}
headerDecode := &Header{}
if err := headerDecode.DecodeBinary(buf); err != nil {
t.Fatal(err)
}
if header.Version != headerDecode.Version {
t.Fatal("expected both versions to be equal")
}
if !header.PrevHash.Equals(headerDecode.PrevHash) {
t.Fatal("expected both prev hashes to be equal")
}
if !header.MerkleRoot.Equals(headerDecode.MerkleRoot) {
t.Fatal("expected both merkle roots to be equal")
}
if header.Index != headerDecode.Index {
t.Fatal("expected both indexes to be equal")
}
if header.ConsensusData != headerDecode.ConsensusData {
t.Fatal("expected both consensus data fields to be equal")
}
if !header.NextConsensus.Equals(headerDecode.NextConsensus) {
t.Fatalf("expected both next consensus fields to be equal")
}
if bytes.Compare(header.Script.InvocationScript, headerDecode.Script.InvocationScript) != 0 {
t.Fatalf("expected equal invocation scripts %v and %v", header.Script.InvocationScript, headerDecode.Script.InvocationScript)
}
if bytes.Compare(header.Script.VerificationScript, headerDecode.Script.VerificationScript) != 0 {
t.Fatalf("expected equal verification scripts %v and %v", header.Script.VerificationScript, headerDecode.Script.VerificationScript)
}
}

View file

@ -32,5 +32,10 @@ func (wit *Witness) DecodeBinary(r io.Reader) error {
// EncodeBinary implements the payload interface. // EncodeBinary implements the payload interface.
func (wit *Witness) EncodeBinary(w io.Writer) error { func (wit *Witness) EncodeBinary(w io.Writer) error {
return nil util.WriteVarUint(w, uint64(len(wit.InvocationScript)))
if err := binary.Write(w, binary.LittleEndian, wit.InvocationScript); err != nil {
return err
}
util.WriteVarUint(w, uint64(len(wit.VerificationScript)))
return binary.Write(w, binary.LittleEndian, wit.VerificationScript)
} }

View file

@ -49,7 +49,7 @@ func (p *AddrWithTime) EncodeBinary(w io.Writer) error {
return err return err
} }
// AddressList holds a slice of AddrWithTime. // AddressList is a list with AddrWithTime.
type AddressList struct { type AddressList struct {
Addrs []*AddrWithTime Addrs []*AddrWithTime
} }

View file

@ -33,14 +33,13 @@ func TestEncodeDecodeAddr(t *testing.T) {
func TestEncodeDecodeAddressList(t *testing.T) { func TestEncodeDecodeAddressList(t *testing.T) {
var lenList uint8 = 4 var lenList uint8 = 4
addrs := make([]*AddrWithTime, lenList) addrList := &AddressList{make([]*AddrWithTime, lenList)}
for i := 0; i < int(lenList); i++ { for i := 0; i < int(lenList); i++ {
e, _ := util.EndpointFromString(fmt.Sprintf("127.0.0.1:200%d", i)) e, _ := util.EndpointFromString(fmt.Sprintf("127.0.0.1:200%d", i))
addrs[i] = NewAddrWithTime(e) addrList.Addrs[i] = NewAddrWithTime(e)
} }
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
addrList := &AddressList{addrs}
if err := addrList.EncodeBinary(buf); err != nil { if err := addrList.EncodeBinary(buf); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -2,7 +2,6 @@ package payload
import ( import (
"encoding/binary" "encoding/binary"
"fmt"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
@ -18,21 +17,23 @@ type GetBlocks struct {
// NewGetBlocks return a pointer to a GetBlocks object. // NewGetBlocks return a pointer to a GetBlocks object.
func NewGetBlocks(start []util.Uint256, stop util.Uint256) *GetBlocks { func NewGetBlocks(start []util.Uint256, stop util.Uint256) *GetBlocks {
p := &GetBlocks{} return &GetBlocks{
p.HashStart = start HashStart: start,
p.HashStop = stop HashStop: stop,
return p }
} }
// DecodeBinary implements the payload interface. // DecodeBinary implements the payload interface.
func (p *GetBlocks) DecodeBinary(r io.Reader) error { func (p *GetBlocks) DecodeBinary(r io.Reader) error {
lenStart := util.ReadVarUint(r) lenStart := util.ReadVarUint(r)
fmt.Println(lenStart)
p.HashStart = make([]util.Uint256, lenStart) p.HashStart = make([]util.Uint256, lenStart)
err := binary.Read(r, binary.LittleEndian, &p.HashStart)
err = binary.Read(r, binary.LittleEndian, &p.HashStop)
fmt.Println(p) if err := binary.Read(r, binary.LittleEndian, &p.HashStart); err != nil {
return err
}
// If the reader returns EOF we know the hashStop is not encoded.
err := binary.Read(r, binary.LittleEndian, &p.HashStop)
if err == io.EOF { if err == io.EOF {
return nil return nil
} }
@ -42,11 +43,20 @@ func (p *GetBlocks) DecodeBinary(r io.Reader) error {
// EncodeBinary implements the payload interface. // EncodeBinary implements the payload interface.
func (p *GetBlocks) EncodeBinary(w io.Writer) error { func (p *GetBlocks) EncodeBinary(w io.Writer) error {
err := util.WriteVarUint(w, uint64(len(p.HashStart))) if err := util.WriteVarUint(w, uint64(len(p.HashStart))); err != nil {
err = binary.Write(w, binary.LittleEndian, p.HashStart) return err
//err = binary.Write(w, binary.LittleEndian, p.HashStop) }
if err := binary.Write(w, binary.LittleEndian, p.HashStart); err != nil {
return err
}
return err // Only write hashStop if its not filled with zero bytes.
var emtpy util.Uint256
if p.HashStop != emtpy {
return binary.Write(w, binary.LittleEndian, p.HashStop)
}
return nil
} }
// Size implements the payload interface. // Size implements the payload interface.

View file

@ -1,58 +1,60 @@
package payload package payload
// TODO: Currently the hashstop is not encoded, therefore this test will fail. import (
// Need to figure some stuff how to handle this properly. "bytes"
// - anthdm 04/02/2018 "crypto/sha256"
"reflect"
"testing"
// func TestGetBlocksEncodeDecode(t *testing.T) { "github.com/CityOfZion/neo-go/pkg/util"
// hash, _ := util.Uint256DecodeFromString("d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf") )
// start := []util.Uint256{ func TestGetBlockEncodeDecode(t *testing.T) {
// hash, start := []util.Uint256{
// sha256.Sum256([]byte("a")), sha256.Sum256([]byte("a")),
// sha256.Sum256([]byte("b")), sha256.Sum256([]byte("b")),
// sha256.Sum256([]byte("c")), sha256.Sum256([]byte("c")),
// } sha256.Sum256([]byte("d")),
// stop := sha256.Sum256([]byte("d")) }
// p := NewGetBlocks(start, stop) p := NewGetBlocks(start, util.Uint256{})
// buf := new(bytes.Buffer) buf := new(bytes.Buffer)
// if err := p.EncodeBinary(buf); err != nil { if err := p.EncodeBinary(buf); err != nil {
// t.Fatal(err) t.Fatal(err)
// } }
// pDecode := &GetBlocks{} pDecode := &GetBlocks{}
// if err := pDecode.DecodeBinary(buf); err != nil { if err := pDecode.DecodeBinary(buf); err != nil {
// t.Fatal(err) t.Fatal(err)
// } }
// if !reflect.DeepEqual(p, pDecode) { if !reflect.DeepEqual(p, pDecode) {
// t.Fatalf("expecting both getblocks payloads to be equal %v and %v", p, pDecode) t.Fatalf("expected to have equal block payload %v and %v", p, pDecode)
// } }
// } }
// TODO: Currently the hashstop is not encoded, therefore this test will fail. func TestGetBlockEncodeDecodeWithHashStop(t *testing.T) {
// Need to figure some stuff how to handle this properly. var (
// - anthdm 04/02/2018 start = []util.Uint256{
// sha256.Sum256([]byte("a")),
// func TestGetBlocksWithEmptyHashStop(t *testing.T) { sha256.Sum256([]byte("b")),
// start := []util.Uint256{ sha256.Sum256([]byte("c")),
// sha256.Sum256([]byte("a")), sha256.Sum256([]byte("d")),
// } }
// stop := util.Uint256{} stop = sha256.Sum256([]byte("e"))
)
p := NewGetBlocks(start, stop)
buf := new(bytes.Buffer)
if err := p.EncodeBinary(buf); err != nil {
t.Fatal(err)
}
// buf := new(bytes.Buffer) pDecode := &GetBlocks{}
// p := NewGetBlocks(start, stop) if err := pDecode.DecodeBinary(buf); err != nil {
// if err := p.EncodeBinary(buf); err != nil { t.Fatal(err)
// t.Fatal(err) }
// }
// pDecode := &GetBlocks{} if !reflect.DeepEqual(p, pDecode) {
// if err := pDecode.DecodeBinary(buf); err != nil { t.Fatalf("expected to have equal block payload %v and %v", p, pDecode)
// t.Fatal(err) }
// } }
// if !reflect.DeepEqual(p, pDecode) {
// t.Fatalf("expecting both getblocks payloads to be equal %v and %v", p, pDecode)
// }
// }

View file

@ -30,6 +30,13 @@ func (p *Headers) DecodeBinary(r io.Reader) error {
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (h *Headers) EncodeBinary(w io.Writer) error { func (p *Headers) EncodeBinary(w io.Writer) error {
util.WriteVarUint(w, uint64(len(p.Hdrs)))
for _, header := range p.Hdrs {
if err := header.EncodeBinary(w); err != nil {
return err
}
}
return nil return nil
} }

View file

@ -0,0 +1,55 @@
package payload
import (
"bytes"
"reflect"
"testing"
"github.com/CityOfZion/neo-go/pkg/core"
)
func TestHeadersEncodeDecode(t *testing.T) {
headers := &Headers{[]*core.Header{
&core.Header{
BlockBase: core.BlockBase{
Version: 0,
Index: 1,
Script: &core.Witness{
InvocationScript: []byte{0x0},
VerificationScript: []byte{0x1},
},
}},
&core.Header{
BlockBase: core.BlockBase{
Version: 0,
Index: 2,
Script: &core.Witness{
InvocationScript: []byte{0x0},
VerificationScript: []byte{0x1},
},
}},
&core.Header{
BlockBase: core.BlockBase{
Version: 0,
Index: 3,
Script: &core.Witness{
InvocationScript: []byte{0x0},
VerificationScript: []byte{0x1},
},
}},
}}
buf := new(bytes.Buffer)
if err := headers.EncodeBinary(buf); err != nil {
t.Fatal(err)
}
headersDecode := &Headers{}
if err := headersDecode.DecodeBinary(buf); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(headers, headersDecode) {
t.Fatalf("expected both header payload to be equal %+v and %+v", headers, headersDecode)
}
}

View file

@ -41,7 +41,8 @@ func (p *LocalPeer) version() *payload.Version {
} }
func (p *LocalPeer) callVersion(msg *Message) error { func (p *LocalPeer) callVersion(msg *Message) error {
return p.s.handleVersionCmd(msg, p) version := msg.Payload.(*payload.Version)
return p.s.handleVersionCmd(version, p)
} }
func (p *LocalPeer) callVerack(msg *Message) error { func (p *LocalPeer) callVerack(msg *Message) error {

View file

@ -212,8 +212,7 @@ func (s *Server) handlePeerConnected(p Peer) error {
return p.callVersion(msg) return p.callVersion(msg)
} }
func (s *Server) handleVersionCmd(msg *Message, p Peer) error { func (s *Server) handleVersionCmd(version *payload.Version, p Peer) error {
version := msg.Payload.(*payload.Version)
if s.id == version.Nonce { if s.id == version.Nonce {
return errors.New("identical nonce") return errors.New("identical nonce")
} }
@ -230,8 +229,7 @@ func (s *Server) handleGetaddrCmd(msg *Message, p Peer) error {
// The node can broadcast the object information it owns by this message. // The node can broadcast the object information it owns by this message.
// The message can be sent automatically or can be used to answer getbloks messages. // The message can be sent automatically or can be used to answer getbloks messages.
func (s *Server) handleInvCmd(msg *Message, p Peer) error { func (s *Server) handleInvCmd(inv *payload.Inventory, p Peer) error {
inv := msg.Payload.(*payload.Inventory)
if !inv.Type.Valid() { if !inv.Type.Valid() {
return fmt.Errorf("invalid inventory type %s", inv.Type) return fmt.Errorf("invalid inventory type %s", inv.Type)
} }
@ -248,8 +246,7 @@ func (s *Server) handleInvCmd(msg *Message, p Peer) error {
} }
// handleBlockCmd processes the received block. // handleBlockCmd processes the received block.
func (s *Server) handleBlockCmd(msg *Message, p Peer) error { func (s *Server) handleBlockCmd(block *core.Block, p Peer) error {
block := msg.Payload.(*core.Block)
hash, err := block.Hash() hash, err := block.Hash()
if err != nil { if err != nil {
return err return err
@ -262,8 +259,7 @@ func (s *Server) handleBlockCmd(msg *Message, p Peer) error {
// After receiving the getaddr message, the node returns an addr message as response // After receiving the getaddr message, the node returns an addr message as response
// and provides information about the known nodes on the network. // and provides information about the known nodes on the network.
func (s *Server) handleAddrCmd(msg *Message, p Peer) error { func (s *Server) handleAddrCmd(addrList *payload.AddressList, p Peer) error {
addrList := msg.Payload.(*payload.AddressList)
for _, addr := range addrList.Addrs { for _, addr := range addrList.Addrs {
if !s.peerAlreadyConnected(addr.Addr) { if !s.peerAlreadyConnected(addr.Addr) {
// TODO: this is not transport abstracted. // TODO: this is not transport abstracted.
@ -285,13 +281,11 @@ func (s *Server) handleHeadersCmd(headers *payload.Headers, p Peer) error {
// Ask more headers if we are not in sync with the peer. // Ask more headers if we are not in sync with the peer.
if s.bc.HeaderHeight() < p.version().StartHeight { if s.bc.HeaderHeight() < p.version().StartHeight {
s.logger.Printf("header height %d peer height %d", s.bc.HeaderHeight(), p.version().StartHeight)
if err := s.askMoreHeaders(p); err != nil { if err := s.askMoreHeaders(p); err != nil {
s.logger.Printf("getheaders RPC failed: %s", err) s.logger.Printf("getheaders RPC failed: %s", err)
return return
} }
} }
}(context.TODO(), headers.Hdrs) }(context.TODO(), headers.Hdrs)
return nil return nil
@ -299,7 +293,7 @@ func (s *Server) handleHeadersCmd(headers *payload.Headers, p Peer) error {
// Ask the peer for more headers We use the current block hash as start. // Ask the peer for more headers We use the current block hash as start.
func (s *Server) askMoreHeaders(p Peer) error { func (s *Server) askMoreHeaders(p Peer) error {
start := []util.Uint256{s.bc.CurrentBlockHash()} start := []util.Uint256{s.bc.CurrentHeaderHash()}
payload := payload.NewGetBlocks(start, util.Uint256{}) payload := payload.NewGetBlocks(start, util.Uint256{})
msg := newMessage(s.net, cmdGetHeaders, payload) msg := newMessage(s.net, cmdGetHeaders, payload)

View file

@ -15,8 +15,7 @@ func TestHandleVersionFailWrongPort(t *testing.T) {
p := NewLocalPeer(s) p := NewLocalPeer(s)
version := payload.NewVersion(1337, 1, "/NEO:0.0.0/", 0, true) version := payload.NewVersion(1337, 1, "/NEO:0.0.0/", 0, true)
msg := newMessage(ModeDevNet, cmdVersion, version) if err := s.handleVersionCmd(version, p); err == nil {
if err := s.handleVersionCmd(msg, p); err == nil {
t.Fatal("expected error got nil") t.Fatal("expected error got nil")
} }
} }
@ -28,8 +27,7 @@ func TestHandleVersionFailIdenticalNonce(t *testing.T) {
p := NewLocalPeer(s) p := NewLocalPeer(s)
version := payload.NewVersion(s.id, 1, "/NEO:0.0.0/", 0, true) version := payload.NewVersion(s.id, 1, "/NEO:0.0.0/", 0, true)
msg := newMessage(ModeDevNet, cmdVersion, version) if err := s.handleVersionCmd(version, p); err == nil {
if err := s.handleVersionCmd(msg, p); err == nil {
t.Fatal("expected error got nil") t.Fatal("expected error got nil")
} }
} }
@ -41,9 +39,7 @@ func TestHandleVersion(t *testing.T) {
p := NewLocalPeer(s) p := NewLocalPeer(s)
version := payload.NewVersion(1337, p.addr().Port, "/NEO:0.0.0/", 0, true) version := payload.NewVersion(1337, p.addr().Port, "/NEO:0.0.0/", 0, true)
msg := newMessage(ModeDevNet, cmdVersion, version) if err := s.handleVersionCmd(version, p); err != nil {
if err := s.handleVersionCmd(msg, p); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"net" "net"
"github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/network/payload" "github.com/CityOfZion/neo-go/pkg/network/payload"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -84,10 +85,10 @@ func handleMessage(s *Server, p *TCPPeer) {
switch command { switch command {
case cmdVersion: case cmdVersion:
if err = s.handleVersionCmd(msg, p); err != nil { version := msg.Payload.(*payload.Version)
if err = s.handleVersionCmd(version, p); err != nil {
break break
} }
version := msg.Payload.(*payload.Version)
p.nonce = version.Nonce p.nonce = version.Nonce
p.pVersion = version p.pVersion = version
@ -106,19 +107,22 @@ func handleMessage(s *Server, p *TCPPeer) {
// start the protocol // start the protocol
go s.startProtocol(p) go s.startProtocol(p)
case cmdAddr: case cmdAddr:
err = s.handleAddrCmd(msg, p) addrList := msg.Payload.(*payload.AddressList)
err = s.handleAddrCmd(addrList, p)
case cmdGetAddr: case cmdGetAddr:
err = s.handleGetaddrCmd(msg, p) err = s.handleGetaddrCmd(msg, p)
case cmdInv: case cmdInv:
err = s.handleInvCmd(msg, p) inv := msg.Payload.(*payload.Inventory)
err = s.handleInvCmd(inv, p)
case cmdBlock: case cmdBlock:
err = s.handleBlockCmd(msg, p) block := msg.Payload.(*core.Block)
err = s.handleBlockCmd(block, p)
case cmdConsensus: case cmdConsensus:
case cmdTX: case cmdTX:
case cmdVerack: case cmdVerack:
// If we receive a verack here we disconnect. We already handled the verack // If we receive a verack here we disconnect. We already handled the verack
// when we sended our version. // when we sended our version.
err = errors.New("received verack twice") err = errors.New("verack already received")
case cmdGetHeaders: case cmdGetHeaders:
case cmdGetBlocks: case cmdGetBlocks:
case cmdGetData: case cmdGetData:
@ -284,6 +288,7 @@ func (p *TCPPeer) writeLoop() {
p.disconnect() p.disconnect()
}() }()
// resuse this buffer
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
for { for {
t := <-p.send t := <-p.send

View file

@ -22,3 +22,8 @@ func (u Uint160) ToSlice() []byte {
func (u Uint160) String() string { func (u Uint160) String() string {
return hex.EncodeToString(u.ToSlice()) return hex.EncodeToString(u.ToSlice())
} }
// Equals returns true if both Uint256 values are the same.
func (u Uint160) Equals(other Uint160) bool {
return u.String() == other.String()
}