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:
parent
046494dd68
commit
b6d8271b8d
18 changed files with 290 additions and 106 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
0.7.0
|
0.8.0
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
61
pkg/core/header_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
//err = binary.Write(w, binary.LittleEndian, p.HashStop)
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
if err := binary.Write(w, binary.LittleEndian, p.HashStart); err != nil {
|
||||||
|
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.
|
||||||
|
|
|
@ -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)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
55
pkg/network/payload/headers_test.go
Normal file
55
pkg/network/payload/headers_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue