added core block type
This commit is contained in:
parent
05e3a115af
commit
e9f9354b86
9 changed files with 128 additions and 7 deletions
|
@ -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
28
pkg/core/block.go
Normal 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
4
pkg/core/transaction.go
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
// Transaction is a process recorded in the NEO system.
|
||||||
|
type Transaction struct{}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
32
pkg/network/payload/inventory_test.go
Normal file
32
pkg/network/payload/inventory_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
Loading…
Reference in a new issue