added core block type

This commit is contained in:
anthdm 2018-01-30 11:56:36 +01:00
parent 05e3a115af
commit e9f9354b86
9 changed files with 128 additions and 7 deletions

View file

@ -7,7 +7,7 @@
<h1 align="center">NEO-GO</h1> <h1 align="center">NEO-GO</h1>
<p align="center"> <p align="center">
Node and SDK for the <b>NEO</b> blockchain written in the <b>Go</b> language. Node and SDK for the <b>NEO</b> blockchain written in the <b>Go</b> language.
</p> </p>
<p align="center"> <p align="center">
@ -20,7 +20,7 @@
### Long term project goals ### Long term project goals
Full port of the original C# [NEO project](https://github.com/neo-project). A complete toolkit for the NEO blockchain. Full port of the original C# [NEO project](https://github.com/neo-project). A complete toolkit for the NEO blockchain.
- Full server (consensus, RPC and bookkeeping) nodes. - Full server (consensus and RPC) nodes.
- RPC client - RPC client
- build, compile and deploy smart contracts with the Go vm - build, compile and deploy smart contracts with the Go vm

28
pkg/core/block.go Normal file
View file

@ -0,0 +1,28 @@
package core
import (
. "github.com/anthdm/neo-go/pkg/util"
)
// Block represents one block in the chain.
type Block struct {
Version uint32
// hash of the previous block.
PrevBlock Uint256
// Root hash of a transaction list.
MerkleRoot Uint256
// timestamp
Timestamp uint32
// height of the block
Height uint32
// Random number
Nonce uint64
// contract addresss of the next miner
NextMiner Uint160
// seperator ? fixed to 1
_sep uint8
// Script used to validate the block
Script []byte
// transaction list
Transactions []*Transaction
}

4
pkg/core/transaction.go Normal file
View file

@ -0,0 +1,4 @@
package core
// Transaction is a process recorded in the NEO system.
type Transaction struct{}

View file

@ -83,6 +83,7 @@ const (
cmdGetData = "getdata" cmdGetData = "getdata"
cmdBlock = "block" cmdBlock = "block"
cmdTX = "tx" cmdTX = "tx"
cmdConsensus = "consensus"
) )
func newMessage(magic NetMode, cmd commandType, p payload.Payload) *Message { func newMessage(magic NetMode, cmd commandType, p payload.Payload) *Message {
@ -137,6 +138,8 @@ func (m *Message) commandType() commandType {
return cmdBlock return cmdBlock
case "tx": case "tx":
return cmdTX return cmdTX
case "consensus":
return cmdConsensus
default: default:
return "" return ""
} }
@ -149,6 +152,8 @@ func (m *Message) decode(r io.Reader) error {
binary.Read(r, binary.LittleEndian, &m.Length) binary.Read(r, binary.LittleEndian, &m.Length)
binary.Read(r, binary.LittleEndian, &m.Checksum) binary.Read(r, binary.LittleEndian, &m.Checksum)
fmt.Println(cmdByteArrayToString(m.Command))
// return if their is no payload. // return if their is no payload.
if m.Length == 0 { if m.Length == 0 {
return nil return nil
@ -164,6 +169,8 @@ func (m *Message) decodePayload(r io.Reader) error {
return err return err
} }
fmt.Printf("The length of the payload is %d\n", n)
if uint32(n) != m.Length { if uint32(n) != m.Length {
return fmt.Errorf("expected to have read exactly %d bytes got %d", m.Length, n) return fmt.Errorf("expected to have read exactly %d bytes got %d", m.Length, n)
} }

View file

@ -27,6 +27,11 @@ func (i InventoryType) String() string {
} }
} }
// Valid returns true if the inventory (type) is known.
func (i InventoryType) Valid() bool {
return i == BlockType || i == TXType || i == ConsensusType
}
// List of valid InventoryTypes. // List of valid InventoryTypes.
const ( const (
BlockType InventoryType = 0x01 // 1 BlockType InventoryType = 0x01 // 1
@ -39,7 +44,15 @@ type Inventory struct {
// Type if the object hash. // Type if the object hash.
Type InventoryType Type InventoryType
// The hash of the object (uint256). // The hash of the object (uint256).
Hash Uint256 Hashes []Uint256
}
// NewInventory return a pointer to an Inventory.
func NewInventory(typ InventoryType, hashes []Uint256) *Inventory {
return &Inventory{
Type: typ,
Hashes: hashes,
}
} }
// DecodeBinary implements the Payload interface. // DecodeBinary implements the Payload interface.
@ -50,15 +63,30 @@ func (p *Inventory) DecodeBinary(r io.Reader) error {
var listLen uint8 var listLen uint8
err := binary.Read(r, binary.LittleEndian, &p.Type) err := binary.Read(r, binary.LittleEndian, &p.Type)
err = binary.Read(r, binary.LittleEndian, &listLen) err = binary.Read(r, binary.LittleEndian, &listLen)
err = binary.Read(r, binary.LittleEndian, &p.Hash)
p.Hashes = make([]Uint256, listLen)
for i := 0; i < int(listLen); i++ {
if err := binary.Read(r, binary.LittleEndian, &p.Hashes[i]); err != nil {
return err
}
}
return err return err
} }
// EncodeBinary implements the Payload interface. // EncodeBinary implements the Payload interface.
func (p *Inventory) EncodeBinary(w io.Writer) error { func (p *Inventory) EncodeBinary(w io.Writer) error {
// TODO listLen := uint8(len(p.Hashes))
return nil err := binary.Write(w, binary.LittleEndian, p.Type)
err = binary.Write(w, binary.LittleEndian, listLen)
for i := 0; i < len(p.Hashes); i++ {
if err := binary.Write(w, binary.LittleEndian, p.Hashes[i]); err != nil {
return err
}
}
return err
} }
// Size implements the Payloader interface. // Size implements the Payloader interface.

View file

@ -0,0 +1,32 @@
package payload
import (
"bytes"
"crypto/sha256"
"reflect"
"testing"
. "github.com/anthdm/neo-go/pkg/util"
)
func TestInventoryEncodeDecode(t *testing.T) {
hashes := []Uint256{
sha256.Sum256([]byte("a")),
sha256.Sum256([]byte("b")),
}
inv := NewInventory(BlockType, hashes)
buf := new(bytes.Buffer)
if err := inv.EncodeBinary(buf); err != nil {
t.Fatal(err)
}
invDecode := &Inventory{}
if err := invDecode.DecodeBinary(buf); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(inv, invDecode) {
t.Fatalf("expected both inventories to be equal %v and %v", inv, invDecode)
}
}

View file

@ -189,9 +189,11 @@ func (s *Server) processMessage(msg *Message, peer *Peer) error {
case cmdHeaders: case cmdHeaders:
case cmdGetBlocks: case cmdGetBlocks:
case cmdInv: case cmdInv:
return s.handleInvCmd(msg.Payload.(*payload.Inventory), peer)
case cmdGetData: case cmdGetData:
case cmdBlock: case cmdBlock:
case cmdTX: case cmdTX:
case cmdConsensus:
default: default:
return fmt.Errorf("invalid RPC command received: %s", command) return fmt.Errorf("invalid RPC command received: %s", command)
} }
@ -241,6 +243,22 @@ func (s *Server) handleAddrCmd(addrList *payload.AddressList, peer *Peer) error
return nil return nil
} }
func (s *Server) handleInvCmd(inv *payload.Inventory, peer *Peer) error {
if !inv.Type.Valid() {
return fmt.Errorf("invalid inventory type: %s", inv.Type)
}
if len(inv.Hashes) == 0 {
return nil
}
payload := payload.NewInventory(inv.Type, inv.Hashes)
msg := newMessage(s.net, cmdGetData, payload)
peer.send <- msg
return nil
}
func (s *Server) peerAlreadyConnected(addr net.Addr) bool { func (s *Server) peerAlreadyConnected(addr net.Addr) bool {
// TODO: check for race conditions // TODO: check for race conditions
//s.mtx.RLock() //s.mtx.RLock()

View file

@ -7,7 +7,8 @@ import (
"fmt" "fmt"
) )
// Uint256 ... // Uint256 is a 32 byte long unsigned integer.
// Commonly used to store hashes.
type Uint256 [32]uint8 type Uint256 [32]uint8
// Uint256FromBytes return an Uint256 from a byte slice. // Uint256FromBytes return an Uint256 from a byte slice.
@ -44,3 +45,6 @@ func (u Uint256) ToSlice() []byte {
func (u Uint256) String() string { func (u Uint256) String() string {
return hex.EncodeToString(u.ToSlice()) return hex.EncodeToString(u.ToSlice())
} }
// Uint160 is a 20 byte long unsigned integer
type Uint160 [20]uint8