neoneo-go/pkg/peer
decentralisedkev c1b6738bdb
VM: Add basic vm (#166)
* VM:Add abstract stack item

* VM: Add stackItems; Array, Boolean, Int and ByteArray

* VM: Add tests for stack item

* VM: first pass at Random Access Stack object

* VM: Add Sub, Mul, Mod LSH, RSH

* VM: moved test helper functions into separate file

* VM: removed helper functions from stack_test.go

* Add conversions for bytearray and Int stack items

* Add instructions file for vm

* - Add guide to stack readme
- Add testReadInt64

* Add Builder

* Refactor Int, Boolean, ByteArray conversion

* Add Context stack Item

* Add Invocation stack - convenience RAS

* rename testhelper to test_helper

* Move opcode file

* - Add `Add` OpCode
- Add Opcode Function map

* - Add test for math `Add` opcode
- basic opcode execution

* Add popTwoIntegers convenience func

* Add `SUB` Opcode

* Export Context Read methods
- Return errors where failable

* - Add `Op` to handleOP func signature
- Add PushNBytes OPcode

* remove error on NewBoolean
- Expose underlying with Getter on Boolean StackItem
- Add Equals method for ByteArray

* Make Next() method on Context failable, refactor peekContext and Peek

* Add ExecuteOp, Step and Run methods on the VM

* Add Equal Opcode

* Add THROWIFNOT Opcode

* Add RET Opcode

* Refactor PushNBytes Opcode

* refactor Add, Sub to return VMSTATE
add popTwoByteArrays helper function

* Add basic tests for vm

* clarify vm states

* Add astack

* [VM]

Pass ResultStack to the opcode handlers

* [VM]

refactor handlers to have rstack as argument

* [Stack]

- Change RemoveCurrentContext for PopCurrentContext
- Add CopTo method to stack

* [VM]

Add Result stack Len check in simple run test

* [VM] fix typo

* [Peer/Stall]

Change seconds to milliseconds in test
2019-03-18 21:40:21 +00:00
..
stall VM: Add basic vm (#166) 2019-03-18 21:40:21 +00:00
config.go Fix lint errors (#182) 2019-03-17 18:26:35 +00:00
peer.go Fix lint errors (#182) 2019-03-17 18:26:35 +00:00
peer_test.go Initial commit 2019-02-25 22:44:14 +00:00
peerhandshake.go Fix lint errors (#182) 2019-03-17 18:26:35 +00:00
readme.md Initial commit 2019-02-25 22:44:14 +00:00

Package - Peer

Responsibility

Once a connection has been made. The connection will represent a established peer to the localNode. Since a connection and the Wire is a golang primitive, that we cannot do much with. The peer package will encapsulate both, while adding extra functionality.

Features

  • The handshake protocol is automatically executed and handled by the peer package. If a Version/Verack is received twice, the peer will be disconnected.

  • IdleTimeouts: If a Message is not received from the peer within a set period of time, the peer will be disconnected.

  • StallTimeouts: For Example, If a GetHeaders, is sent to the Peer and a Headers Response is not received within a certain period of time, then the peer is disconnected.

  • Concurrency Model: The concurrency model used is similar to Actor model, with a few changes. Messages can be sent to a peer asynchronously or synchronously. An example of an synchornous message send is the RequestHeaders method, where the channel blocks until an error value is received. The OnHeaders message is however asynchronously called. Furthermore, all methods passed through the config, are wrapped inside of an additional Peers method, this is to lay the ground work to capturing statistics regarding a specific command. These are also used so that we can pass behaviour to be executed down the channel.

  • Configuration: Each Peer will have a config struct passed to it, with information about the Local Peer and functions that will encapsulate the behaviour of what the peer should do, given a request. This way, the peer is not dependent on any other package.

Usage

conn, err := net.Dial("tcp", "seed2.neo.org:10333")
if err != nil {
	fmt.Println("Error dialing connection", err.Error())
	return
}

config := peer.LocalConfig{
	Net:         protocol.MainNet,
	UserAgent:   "NEO-G",
	Services:    protocol.NodePeerService,
	Nonce:       1200,
	ProtocolVer: 0,
	Relay:       false,
	Port:        10332,
	StartHeight: LocalHeight,
	OnHeader:    OnHeader,
}

p := peer.NewPeer(conn, false, config)
err = p.Run()

hash, err := util.Uint256DecodeString(chainparams.GenesisHash)
// hash2, err := util.Uint256DecodeString("ff8fe95efc5d1cc3a22b17503aecaf289cef68f94b79ddad6f613569ca2342d8")
err = p.RequestHeaders(hash)

func OnHeader(peer *peer.Peer, msg *payload.HeadersMessage) {
    // This function is passed to peer
    // and the peer will execute it on receiving a header
}

func LocalHeight() uint32 {
    // This will be a function from the object that handles the block heights
    return 10
}

Notes

Should we follow the actor model for Peers? Each Peer will have a ID, which we can take as the PID or if we launch a go-routine for each peer, then we can use that as an implicit PID.

Peer information should be stored into a database, if no db exists, we should get it from an initial peers file. We can use this to periodically store information about a peer.