Merge branch 'dev' into vm

This commit is contained in:
BlockChainDev 2019-03-17 18:30:48 +00:00
commit 5e26b40b5e
70 changed files with 502 additions and 258 deletions

1
go.mod
View file

@ -4,5 +4,6 @@ require (
github.com/o3labs/neo-utils v0.0.0-20190129071622-8ae0bc31751f github.com/o3labs/neo-utils v0.0.0-20190129071622-8ae0bc31751f
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb v1.0.0
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c // indirect
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b
) )

3
go.sum
View file

@ -22,6 +22,8 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c h1:Rx/HTKi09myZ25t1SOlDHmHOy/mKxNAcu0hP1oPX9qM=
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX1gxn7irUTF1fLpQovfQ5M= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX1gxn7irUTF1fLpQovfQ5M=
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
@ -40,3 +42,4 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View file

@ -5,7 +5,7 @@ import (
"crypto/cipher" "crypto/cipher"
) )
// AESEncrypt encrypts the key with the given source. // Encrypt encrypts the key with the given source.
func Encrypt(src, key []byte) ([]byte, error) { func Encrypt(src, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
@ -19,7 +19,7 @@ func Encrypt(src, key []byte) ([]byte, error) {
return out, nil return out, nil
} }
// AESDecrypt decrypts the encrypted source with the given key. // Decrypt decrypts the encrypted source with the given key.
func Decrypt(crypted, key []byte) ([]byte, error) { func Decrypt(crypted, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {

View file

@ -22,7 +22,7 @@ var decodeMap = map[rune]int64{
'x': 55, 'y': 56, 'z': 57, 'x': 55, 'y': 56, 'z': 57,
} }
// Base58Decode decodes the base58 encoded string. // Decode decodes the base58 encoded string.
func Decode(s string) ([]byte, error) { func Decode(s string) ([]byte, error) {
var ( var (
startIndex = 0 startIndex = 0
@ -58,7 +58,7 @@ func Decode(s string) ([]byte, error) {
return buf, nil return buf, nil
} }
// Base58Encode encodes a byte slice to be a base58 encoded string. // Encode encodes a byte slice to be a base58 encoded string.
func Encode(bytes []byte) string { func Encode(bytes []byte) string {
var ( var (
lookupTable = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" lookupTable = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

View file

@ -18,10 +18,13 @@ var curve Curve
type curveType string type curveType string
const ( const (
// Secp256r1 curve type
Secp256r1 curveType = "Secp256r1" Secp256r1 curveType = "Secp256r1"
// Secp256k1 curve type
Secp256k1 curveType = "Secp256k1" Secp256k1 curveType = "Secp256k1"
) )
// SetCurveSecp256r1 Will set the curve parameters to match Secp256r1
func (ChosenCurve *Curve) SetCurveSecp256r1() { func (ChosenCurve *Curve) SetCurveSecp256r1() {
ChosenCurve.P, _ = new(big.Int).SetString("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16) //Q ChosenCurve.P, _ = new(big.Int).SetString("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16) //Q
ChosenCurve.A, _ = new(big.Int).SetString("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16) ChosenCurve.A, _ = new(big.Int).SetString("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16)
@ -33,6 +36,7 @@ func (ChosenCurve *Curve) SetCurveSecp256r1() {
ChosenCurve.Name = "Secp256r1" ChosenCurve.Name = "Secp256r1"
} }
// SetCurveSecp256k1 Will set the curve parameters to match Secp256k1
func (ChosenCurve *Curve) SetCurveSecp256k1() { func (ChosenCurve *Curve) SetCurveSecp256k1() {
ChosenCurve.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16) ChosenCurve.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16)
ChosenCurve.A, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000000", 16) ChosenCurve.A, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000000", 16)
@ -44,6 +48,8 @@ func (ChosenCurve *Curve) SetCurveSecp256k1() {
ChosenCurve.Name = "Secp256k1" ChosenCurve.Name = "Secp256k1"
} }
//NewEllipticCurve will instantiate a new EllipticCurve
//Defaults to secp256r1
func NewEllipticCurve(ct curveType) Curve { func NewEllipticCurve(ct curveType) Curve {
var curve Curve var curve Curve
switch ct { switch ct {

View file

@ -19,8 +19,8 @@ type Point struct {
Y *big.Int Y *big.Int
} }
/* y**2 = x**3 + a*x + b % p */
// Curve represents the parameters of a short Weierstrass equation elliptic curve. // Curve represents the parameters of a short Weierstrass equation elliptic curve.
/* y**2 = x**3 + a*x + b % p */
type Curve struct { type Curve struct {
A *big.Int A *big.Int
B *big.Int B *big.Int
@ -44,6 +44,7 @@ func (p *Point) format() string {
return fmt.Sprintf("(%s,%s)", hex.EncodeToString(p.X.Bytes()), hex.EncodeToString(p.Y.Bytes())) return fmt.Sprintf("(%s,%s)", hex.EncodeToString(p.X.Bytes()), hex.EncodeToString(p.Y.Bytes()))
} }
// Params represent the paramters for the Elliptic Curve
func (ec Curve) Params() *nativeelliptic.CurveParams { func (ec Curve) Params() *nativeelliptic.CurveParams {
return &nativeelliptic.CurveParams{ return &nativeelliptic.CurveParams{
P: ec.P, P: ec.P,
@ -302,12 +303,13 @@ func (ec *Curve) Decompress(x *big.Int, ylsb uint) (P Point, err error) {
P.Y = y P.Y = y
if !ec.IsOnCurve(P.X, P.Y) { if !ec.IsOnCurve(P.X, P.Y) {
return P, errors.New("Compressed (x, ylsb) not on curve.") return P, errors.New("compressed (x, ylsb) not on curve")
} }
return P, nil return P, nil
} }
// Double will return the (x1+x1,y1+y1)
func (ec Curve) Double(x1, y1 *big.Int) (x, y *big.Int) { func (ec Curve) Double(x1, y1 *big.Int) (x, y *big.Int) {
x = &big.Int{} x = &big.Int{}
x.SetBytes([]byte{0x00}) x.SetBytes([]byte{0x00})

View file

@ -8,6 +8,8 @@ import (
"golang.org/x/crypto/ripemd160" "golang.org/x/crypto/ripemd160"
) )
// Sha256 hashes the incoming byte slice
// using the sha256 algorithm
func Sha256(data []byte) (util.Uint256, error) { func Sha256(data []byte) (util.Uint256, error) {
var hash util.Uint256 var hash util.Uint256
hasher := sha256.New() hasher := sha256.New()
@ -21,6 +23,7 @@ func Sha256(data []byte) (util.Uint256, error) {
return hash, nil return hash, nil
} }
// DoubleSha256 performs sha256 twice on the given data
func DoubleSha256(data []byte) (util.Uint256, error) { func DoubleSha256(data []byte) (util.Uint256, error) {
var hash util.Uint256 var hash util.Uint256
@ -36,6 +39,8 @@ func DoubleSha256(data []byte) (util.Uint256, error) {
return hash, nil return hash, nil
} }
// RipeMD160 performs the RIPEMD160 hash algorithm
// on the given data
func RipeMD160(data []byte) (util.Uint160, error) { func RipeMD160(data []byte) (util.Uint160, error) {
var hash util.Uint160 var hash util.Uint160
hasher := ripemd160.New() hasher := ripemd160.New()
@ -49,6 +54,8 @@ func RipeMD160(data []byte) (util.Uint160, error) {
return hash, nil return hash, nil
} }
// Hash160 performs sha256 and then ripemd160
// on the given data
func Hash160(data []byte) (util.Uint160, error) { func Hash160(data []byte) (util.Uint160, error) {
var hash util.Uint160 var hash util.Uint160
h1, err := Sha256(data) h1, err := Sha256(data)
@ -63,6 +70,8 @@ func Hash160(data []byte) (util.Uint160, error) {
return hash, nil return hash, nil
} }
// Checksum returns the checksum for a given piece of data
// using sha256 twice as the hash algorithm
func Checksum(data []byte) ([]byte, error) { func Checksum(data []byte) ([]byte, error) {
hash, err := Sum(data) hash, err := Sum(data)
if err != nil { if err != nil {
@ -71,6 +80,8 @@ func Checksum(data []byte) ([]byte, error) {
return hash[:4], nil return hash[:4], nil
} }
// Sum performs sha256 twice on the given data
// XXX(issue): We should remove this and just do doublesha256
func Sum(b []byte) (util.Uint256, error) { func Sum(b []byte) (util.Uint256, error) {
hash, err := DoubleSha256((b)) hash, err := DoubleSha256((b))
return hash, err return hash, err

View file

@ -23,6 +23,8 @@ type PrivateKey struct {
b []byte b []byte
} }
// NewPrivateKey will create a new private key
// With curve as Secp256r1
func NewPrivateKey() (*PrivateKey, error) { func NewPrivateKey() (*PrivateKey, error) {
curve := elliptic.NewEllipticCurve(elliptic.Secp256r1) curve := elliptic.NewEllipticCurve(elliptic.Secp256r1)
b := make([]byte, curve.N.BitLen()/8+8) b := make([]byte, curve.N.BitLen()/8+8)
@ -38,6 +40,7 @@ func NewPrivateKey() (*PrivateKey, error) {
return p, nil return p, nil
} }
// NewPrivateKeyFromHex will create a new private key hex string
func NewPrivateKeyFromHex(str string) (*PrivateKey, error) { func NewPrivateKeyFromHex(str string) (*PrivateKey, error) {
b, err := hex.DecodeString(str) b, err := hex.DecodeString(str)
if err != nil { if err != nil {
@ -56,6 +59,8 @@ func NewPrivateKeyFromBytes(b []byte) (*PrivateKey, error) {
return &PrivateKey{b}, nil return &PrivateKey{b}, nil
} }
// PublicKey returns a the public corresponding to the private key
// For the curve secp256r1
func (p *PrivateKey) PublicKey() (*publickey.PublicKey, error) { func (p *PrivateKey) PublicKey() (*publickey.PublicKey, error) {
var ( var (
c = elliptic.NewEllipticCurve(elliptic.Secp256r1) c = elliptic.NewEllipticCurve(elliptic.Secp256r1)
@ -78,6 +83,8 @@ func (p *PrivateKey) PublicKey() (*publickey.PublicKey, error) {
} }
// WIFEncode will converts a private key
// to the Wallet Import Format for NEO
func WIFEncode(key []byte) (s string) { func WIFEncode(key []byte) (s string) {
if len(key) != 32 { if len(key) != 32 {
return "invalid private key length" return "invalid private key length"
@ -97,6 +104,7 @@ func WIFEncode(key []byte) (s string) {
return WIF return WIF
} }
// Sign will sign the corresponding data using the private key
func (p *PrivateKey) Sign(data []byte) ([]byte, error) { func (p *PrivateKey) Sign(data []byte) ([]byte, error) {
curve := elliptic.NewEllipticCurve(elliptic.Secp256r1) curve := elliptic.NewEllipticCurve(elliptic.Secp256r1)
key := p.b key := p.b

View file

@ -5,16 +5,29 @@ import (
"github.com/CityOfZion/neo-go/pkg/crypto/privatekey" "github.com/CityOfZion/neo-go/pkg/crypto/privatekey"
) )
// SignDataWithRandomPrivateKey will sign data with
// a random private key, then verify said data
// returning true if Verify returns true
func SignDataWithRandomPrivateKey(data []byte) (bool, error) { func SignDataWithRandomPrivateKey(data []byte) (bool, error) {
hashedData, _ := hash.Sha256(data) hashedData, err := hash.Sha256(data)
privKey, _ := privatekey.NewPrivateKey()
signedData, err := privKey.Sign(data)
pubKey, _ := privKey.PublicKey()
result := pubKey.Verify(signedData, hashedData.Bytes())
if err != nil { if err != nil {
return false, err return false, err
} }
privKey, err := privatekey.NewPrivateKey()
if err != nil {
return false, err
}
signedData, err := privKey.Sign(data)
if err != nil {
return false, err
}
pubKey, err := privKey.PublicKey()
if err != nil {
return false, err
}
result := pubKey.Verify(signedData, hashedData.Bytes())
return result, nil return result, nil
} }

View file

@ -77,6 +77,8 @@ func (p *PublicKey) Bytes() []byte {
return append([]byte{prefix}, paddedX...) return append([]byte{prefix}, paddedX...)
} }
// ToAddress will convert a public key to it's neo-address
func (p *PublicKey) ToAddress() string { func (p *PublicKey) ToAddress() string {
publicKeyBytes := p.Bytes() publicKeyBytes := p.Bytes()
@ -145,6 +147,8 @@ func (p *PublicKey) EncodeBinary(w io.Writer) error {
return binary.Write(w, binary.LittleEndian, p.Bytes()) return binary.Write(w, binary.LittleEndian, p.Bytes())
} }
// Verify returns true if the signature is valid and corresponds
// to the hash and public key
func (p *PublicKey) Verify(signature []byte, hash []byte) bool { func (p *PublicKey) Verify(signature []byte, hash []byte) bool {
publicKey := &ecdsa.PublicKey{} publicKey := &ecdsa.PublicKey{}

View file

@ -12,27 +12,38 @@ import (
"github.com/syndtr/goleveldb/leveldb/errors" "github.com/syndtr/goleveldb/leveldb/errors"
) )
// LDB represents a leveldb object
type LDB struct { type LDB struct {
db *leveldb.DB db *leveldb.DB
path string path string
} }
// Database contains all methods needed for an object to be a database
type Database interface { type Database interface {
// Has checks whether the key is in the database
Has(key []byte) (bool, error) Has(key []byte) (bool, error)
// Put adds the key value pair into the pair
Put(key []byte, value []byte) error Put(key []byte, value []byte) error
// Get returns the value for the given key
Get(key []byte) ([]byte, error) Get(key []byte) ([]byte, error)
// Delete deletes the given value for the key from the database
Delete(key []byte) error Delete(key []byte) error
// Close closes the underlying db object
Close() error Close() error
} }
var ( var (
// TX, HEADER AND UTXO are the prefixes for the db // TX is the prefix used when inserting a tx into the db
TX = []byte("TX") TX = []byte("TX")
// HEADER is the prefix used when inserting a header into the db
HEADER = []byte("HEADER") HEADER = []byte("HEADER")
// LATESTHEADER is the prefix used when inserting the latests header into the db
LATESTHEADER = []byte("LH") LATESTHEADER = []byte("LH")
// UTXO is the prefix used when inserting a utxo into the db
UTXO = []byte("UTXO") UTXO = []byte("UTXO")
) )
// New will return a new leveldb instance
func New(path string) *LDB { func New(path string) *LDB {
db, err := leveldb.OpenFile(path, nil) db, err := leveldb.OpenFile(path, nil)
@ -50,23 +61,32 @@ func New(path string) *LDB {
} }
} }
// Has implements the database interface
func (l *LDB) Has(key []byte) (bool, error) { func (l *LDB) Has(key []byte) (bool, error) {
return l.db.Has(key, nil) return l.db.Has(key, nil)
} }
// Put implements the database interface
func (l *LDB) Put(key []byte, value []byte) error { func (l *LDB) Put(key []byte, value []byte) error {
return l.db.Put(key, value, nil) return l.db.Put(key, value, nil)
} }
// Get implements the database interface
func (l *LDB) Get(key []byte) ([]byte, error) { func (l *LDB) Get(key []byte) ([]byte, error) {
return l.db.Get(key, nil) return l.db.Get(key, nil)
} }
// Delete implements the database interface
func (l *LDB) Delete(key []byte) error { func (l *LDB) Delete(key []byte) error {
return l.db.Delete(key, nil) return l.db.Delete(key, nil)
} }
// Close implements the database interface
func (l *LDB) Close() error { func (l *LDB) Close() error {
return l.db.Close() return l.db.Close()
} }
// AddHeader adds a header into the database
func (l *LDB) AddHeader(header *payload.BlockBase) error { func (l *LDB) AddHeader(header *payload.BlockBase) error {
table := NewTable(l, HEADER) table := NewTable(l, HEADER)
@ -102,6 +122,7 @@ func (l *LDB) AddHeader(header *payload.BlockBase) error {
return table.Put(LATESTHEADER, header.Hash.Bytes()) return table.Put(LATESTHEADER, header.Hash.Bytes())
} }
// AddTransactions adds a set of transactions into the database
func (l *LDB) AddTransactions(blockhash util.Uint256, txs []transaction.Transactioner) error { func (l *LDB) AddTransactions(blockhash util.Uint256, txs []transaction.Transactioner) error {
// SHOULD BE DONE IN BATCH!!!! // SHOULD BE DONE IN BATCH!!!!

View file

@ -1,12 +1,12 @@
package database package database
//Table is an abstract datastructure built on //Table is an abstract data structure built on top of a db
// top of a db
type Table struct { type Table struct {
prefix []byte prefix []byte
db Database db Database
} }
//NewTable creates a new table on the given database
func NewTable(db Database, prefix []byte) *Table { func NewTable(db Database, prefix []byte) *Table {
return &Table{ return &Table{
prefix, prefix,
@ -14,23 +14,31 @@ func NewTable(db Database, prefix []byte) *Table {
} }
} }
// Has implements the database interface
func (t *Table) Has(key []byte) (bool, error) { func (t *Table) Has(key []byte) (bool, error) {
key = append(t.prefix, key...) key = append(t.prefix, key...)
return t.db.Has(key) return t.db.Has(key)
} }
// Put implements the database interface
func (t *Table) Put(key []byte, value []byte) error { func (t *Table) Put(key []byte, value []byte) error {
key = append(t.prefix, key...) key = append(t.prefix, key...)
return t.db.Put(key, value) return t.db.Put(key, value)
} }
// Get implements the database interface
func (t *Table) Get(key []byte) ([]byte, error) { func (t *Table) Get(key []byte) ([]byte, error) {
key = append(t.prefix, key...) key = append(t.prefix, key...)
return t.db.Get(key) return t.db.Get(key)
} }
// Delete implements the database interface
func (t *Table) Delete(key []byte) error { func (t *Table) Delete(key []byte) error {
key = append(t.prefix, key...) key = append(t.prefix, key...)
return t.db.Delete(key) return t.db.Delete(key)
} }
// Close implements the database interface
func (t *Table) Close() error { func (t *Table) Close() error {
return nil return nil
} }

View file

@ -6,7 +6,6 @@ import (
) )
// LocalConfig specifies the properties that should be available for each remote peer // LocalConfig specifies the properties that should be available for each remote peer
type LocalConfig struct { type LocalConfig struct {
Net protocol.Magic Net protocol.Magic
UserAgent string UserAgent string

View file

@ -53,6 +53,7 @@ var (
errHandShakeTimeout = errors.New("Handshake timed out, peers have " + string(handshakeTimeout) + " Seconds to Complete the handshake") errHandShakeTimeout = errors.New("Handshake timed out, peers have " + string(handshakeTimeout) + " Seconds to Complete the handshake")
) )
// Peer represents a peer on the neo network
type Peer struct { type Peer struct {
config LocalConfig config LocalConfig
conn net.Conn conn net.Conn
@ -81,6 +82,7 @@ type Peer struct {
quitch chan struct{} quitch chan struct{}
} }
// NewPeer returns a new NEO peer
func NewPeer(con net.Conn, inbound bool, cfg LocalConfig) *Peer { func NewPeer(con net.Conn, inbound bool, cfg LocalConfig) *Peer {
p := Peer{} p := Peer{}
p.inch = make(chan func(), inputBufferSize) p.inch = make(chan func(), inputBufferSize)
@ -108,7 +110,7 @@ func (p *Peer) Read() (wire.Messager, error) {
return wire.ReadMessage(p.conn, p.config.Net) return wire.ReadMessage(p.conn, p.config.Net)
} }
// Disconnects from a peer // Disconnect disconnects a peer and closes the connection
func (p *Peer) Disconnect() { func (p *Peer) Disconnect() {
// return if already disconnected // return if already disconnected
@ -126,34 +128,54 @@ func (p *Peer) Disconnect() {
} }
// Exposed API functions below // Port returns the peers port
func (p *Peer) Port() uint16 { func (p *Peer) Port() uint16 {
return p.port return p.port
} }
// CreatedAt returns the time at which the connection was made
func (p *Peer) CreatedAt() time.Time { func (p *Peer) CreatedAt() time.Time {
return p.createdAt return p.createdAt
} }
// CanRelay returns true, if the peer can relay information
func (p *Peer) CanRelay() bool { func (p *Peer) CanRelay() bool {
return p.relay return p.relay
} }
// LocalAddr returns this node's local address
func (p *Peer) LocalAddr() net.Addr { func (p *Peer) LocalAddr() net.Addr {
return p.conn.LocalAddr() return p.conn.LocalAddr()
} }
// RemoteAddr returns the remote address of the connected peer
func (p *Peer) RemoteAddr() net.Addr { func (p *Peer) RemoteAddr() net.Addr {
return p.conn.RemoteAddr() return p.conn.RemoteAddr()
} }
// Services returns the services offered by the peer
func (p *Peer) Services() protocol.ServiceFlag { func (p *Peer) Services() protocol.ServiceFlag {
return p.config.Services return p.config.Services
} }
//Inbound returns true whether this peer is an inbound peer
func (p *Peer) Inbound() bool { func (p *Peer) Inbound() bool {
return p.inbound return p.inbound
} }
// UserAgent returns this nodes, useragent
func (p *Peer) UserAgent() string { func (p *Peer) UserAgent() string {
return p.config.UserAgent return p.config.UserAgent
} }
// IsVerackReceived returns true, if this node has
// received a verack from this peer
func (p *Peer) IsVerackReceived() bool { func (p *Peer) IsVerackReceived() bool {
return p.verackReceived return p.verackReceived
} }
//NotifyDisconnect returns once the peer has disconnected
// Blocking
func (p *Peer) NotifyDisconnect() bool { func (p *Peer) NotifyDisconnect() bool {
fmt.Println("Peer has not disconnected yet") fmt.Println("Peer has not disconnected yet")
<-p.quitch <-p.quitch
@ -163,7 +185,7 @@ func (p *Peer) NotifyDisconnect() bool {
//End of Exposed API functions// //End of Exposed API functions//
// Ping not impl. in neo yet, adding it now // PingLoop not impl. in neo yet, adding it now
// will cause this client to disconnect from all other implementations // will cause this client to disconnect from all other implementations
func (p *Peer) PingLoop() { /*not implemented in other neo clients*/ } func (p *Peer) PingLoop() { /*not implemented in other neo clients*/ }
@ -183,7 +205,7 @@ func (p *Peer) Run() error {
} }
// run as a go-routine, will act as our queue for messages // StartProtocol run as a go-routine, will act as our queue for messages
// should be ran after handshake // should be ran after handshake
func (p *Peer) StartProtocol() { func (p *Peer) StartProtocol() {
loop: loop:
@ -201,11 +223,9 @@ loop:
p.Disconnect() p.Disconnect()
} }
// ReadLoop Will block on the read until a message is read
// Should only be called after handshake is complete // Should only be called after handshake is complete
// on a seperate go-routine. // on a seperate go-routine.
// ReadLoop Will block on the read until a message is
// read
func (p *Peer) ReadLoop() { func (p *Peer) ReadLoop() {
idleTimer := time.AfterFunc(idleTimeout, func() { idleTimer := time.AfterFunc(idleTimeout, func() {
@ -271,8 +291,7 @@ loop:
p.Disconnect() p.Disconnect()
} }
// WriteLoop will Queue all messages to be written to // WriteLoop will Queue all messages to be written to the peer.
// the peer.
func (p *Peer) WriteLoop() { func (p *Peer) WriteLoop() {
for atomic.LoadInt32(&p.disconnected) == 0 { for atomic.LoadInt32(&p.disconnected) == 0 {
select { select {
@ -284,17 +303,21 @@ func (p *Peer) WriteLoop() {
} }
} }
// OnGetData is called when a GetData message is received
func (p *Peer) OnGetData(msg *payload.GetDataMessage) { func (p *Peer) OnGetData(msg *payload.GetDataMessage) {
p.inch <- func() { p.inch <- func() {
// fmt.Println(msg.Hashes) if p.config.OnInv != nil {
p.config.OnGetData(msg)
}
fmt.Println("That was an getdata Message please pass func down through config", msg.Command()) fmt.Println("That was an getdata Message please pass func down through config", msg.Command())
} }
} }
//OnTX is callwed when a TX message is received
func (p *Peer) OnTX(msg *payload.TXMessage) { func (p *Peer) OnTX(msg *payload.TXMessage) {
p.inch <- func() { p.inch <- func() {
// fmt.Println(msg.Hashes)
getdata, err := payload.NewGetDataMessage(payload.InvTypeTx) getdata, err := payload.NewGetDataMessage(payload.InvTypeTx)
if err != nil { if err != nil {
fmt.Println("Eor", err) fmt.Println("Eor", err)
@ -302,10 +325,10 @@ func (p *Peer) OnTX(msg *payload.TXMessage) {
id, err := msg.Tx.ID() id, err := msg.Tx.ID()
getdata.AddHash(id) getdata.AddHash(id)
p.Write(getdata) p.Write(getdata)
fmt.Println("That was an tx Message please pass func down through config", msg.Command())
} }
} }
// OnInv is called when a Inv message is received
func (p *Peer) OnInv(msg *payload.InvMessage) { func (p *Peer) OnInv(msg *payload.InvMessage) {
p.inch <- func() { p.inch <- func() {
@ -316,8 +339,7 @@ func (p *Peer) OnInv(msg *payload.InvMessage) {
} }
} }
// OnGetHeaders Listener, outside of the anonymous func will be extra functionality // OnGetHeaders is called when a GetHeaders message is received
// like timing
func (p *Peer) OnGetHeaders(msg *payload.GetHeadersMessage) { func (p *Peer) OnGetHeaders(msg *payload.GetHeadersMessage) {
p.inch <- func() { p.inch <- func() {
if p.config.OnGetHeaders != nil { if p.config.OnGetHeaders != nil {
@ -328,7 +350,7 @@ func (p *Peer) OnGetHeaders(msg *payload.GetHeadersMessage) {
} }
} }
// OnAddr Listener // OnAddr is called when a Addr message is received
func (p *Peer) OnAddr(msg *payload.AddrMessage) { func (p *Peer) OnAddr(msg *payload.AddrMessage) {
p.inch <- func() { p.inch <- func() {
if p.config.OnAddr != nil { if p.config.OnAddr != nil {
@ -339,7 +361,7 @@ func (p *Peer) OnAddr(msg *payload.AddrMessage) {
} }
} }
// OnGetAddr Listener // OnGetAddr is called when a GetAddr message is received
func (p *Peer) OnGetAddr(msg *payload.GetAddrMessage) { func (p *Peer) OnGetAddr(msg *payload.GetAddrMessage) {
p.inch <- func() { p.inch <- func() {
if p.config.OnGetAddr != nil { if p.config.OnGetAddr != nil {
@ -350,7 +372,7 @@ func (p *Peer) OnGetAddr(msg *payload.GetAddrMessage) {
} }
} }
// OnGetBlocks Listener // OnGetBlocks is called when a GetBlocks message is received
func (p *Peer) OnGetBlocks(msg *payload.GetBlocksMessage) { func (p *Peer) OnGetBlocks(msg *payload.GetBlocksMessage) {
p.inch <- func() { p.inch <- func() {
if p.config.OnGetBlocks != nil { if p.config.OnGetBlocks != nil {
@ -360,7 +382,7 @@ func (p *Peer) OnGetBlocks(msg *payload.GetBlocksMessage) {
} }
} }
// OnBlocks Listener // OnBlocks is called when a Blocks message is received
func (p *Peer) OnBlocks(msg *payload.BlockMessage) { func (p *Peer) OnBlocks(msg *payload.BlockMessage) {
p.inch <- func() { p.inch <- func() {
if p.config.OnBlock != nil { if p.config.OnBlock != nil {
@ -386,7 +408,7 @@ func (p *Peer) OnVersion(msg *payload.VersionMessage) error {
return nil return nil
} }
// OnHeaders Listener // OnHeaders is called when a Headers message is received
func (p *Peer) OnHeaders(msg *payload.HeadersMessage) { func (p *Peer) OnHeaders(msg *payload.HeadersMessage) {
fmt.Println("We have received the headers") fmt.Println("We have received the headers")
p.inch <- func() { p.inch <- func() {
@ -396,9 +418,8 @@ func (p *Peer) OnHeaders(msg *payload.HeadersMessage) {
} }
} }
// RequestHeaders will write a getheaders to peer // RequestHeaders will write a getheaders to this peer
func (p *Peer) RequestHeaders(hash util.Uint256) error { func (p *Peer) RequestHeaders(hash util.Uint256) error {
fmt.Println("Sending header request")
c := make(chan error, 0) c := make(chan error, 0)
p.outch <- func() { p.outch <- func() {
p.Detector.AddMessage(command.GetHeaders) p.Detector.AddMessage(command.GetHeaders)
@ -406,14 +427,11 @@ func (p *Peer) RequestHeaders(hash util.Uint256) error {
err = p.Write(getHeaders) err = p.Write(getHeaders)
c <- err c <- err
} }
return <-c return <-c
} }
// RequestBlocks will ask a peer for a block // RequestBlocks will ask this peer for a set of blocks
func (p *Peer) RequestBlocks(hashes []util.Uint256) error { func (p *Peer) RequestBlocks(hashes []util.Uint256) error {
fmt.Println("Requesting block from peer")
c := make(chan error, 0) c := make(chan error, 0)
p.outch <- func() { p.outch <- func() {

View file

@ -7,9 +7,10 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire" "github.com/CityOfZion/neo-go/pkg/wire"
"github.com/CityOfZion/neo-go/pkg/wire/payload" "github.com/CityOfZion/neo-go/pkg/wire/payload"
"github.com/CityOfZion/neo-go/pkg/wire/util/ip" iputils "github.com/CityOfZion/neo-go/pkg/wire/util/ip"
) )
// Handshake will initiate a handshake with this peer
func (p *Peer) Handshake() error { func (p *Peer) Handshake() error {
handshakeErr := make(chan error, 1) handshakeErr := make(chan error, 1)

View file

@ -9,10 +9,9 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/command" "github.com/CityOfZion/neo-go/pkg/wire/command"
) )
// stall detector will keep track of all pendingMessages // Detector (stall detector) will keep track of all pendingMessages
// If any message takes too long to reply // If any message takes too long to reply
// the detector will disconnect the peer // the detector will disconnect the peer
type Detector struct { type Detector struct {
responseTime time.Duration responseTime time.Duration
tickInterval time.Duration tickInterval time.Duration
@ -28,6 +27,7 @@ type Detector struct {
disconnected int32 disconnected int32
} }
// NewDetector will create a new stall detector
// rT is the responseTime and signals how long // rT is the responseTime and signals how long
// a peer has to reply back to a sent message // a peer has to reply back to a sent message
// tickerInterval is how often the detector wil check for stalled messages // tickerInterval is how often the detector wil check for stalled messages
@ -81,9 +81,10 @@ func (d *Detector) Quit() {
close(d.Quitch) close(d.Quitch)
} }
//AddMessage will add a message to the responses map
// Call this function when we send a message to a peer // Call this function when we send a message to a peer
// The command passed through is the command that we sent // The command passed through is the command that we sent
// and not the command we expect to receive // we will then set a timer for the expected message(s)
func (d *Detector) AddMessage(cmd command.Type) { func (d *Detector) AddMessage(cmd command.Type) {
cmds := d.addMessage(cmd) cmds := d.addMessage(cmd)
d.lock.Lock() d.lock.Lock()
@ -93,6 +94,7 @@ func (d *Detector) AddMessage(cmd command.Type) {
d.lock.Unlock() d.lock.Unlock()
} }
// RemoveMessage remove messages from the responses map
// Call this function when we receive a message from // Call this function when we receive a message from
// peer. This will remove the pendingresponse message from the map. // peer. This will remove the pendingresponse message from the map.
// The command passed through is the command we received // The command passed through is the command we received

View file

@ -1,13 +1,19 @@
package pubsub package pubsub
// EventType is an enum
// representing the types of messages we can subscribe to
type EventType int type EventType int
const ( const (
NewBlock EventType = iota // When blockchain connects a new block, it will emit an NewBlock Event // NewBlock is called When blockchain connects a new block, it will emit an NewBlock Event
BadBlock // When blockchain declines a block, it will emit a new block event NewBlock EventType = iota
BadHeader // When blockchain rejects a Header, it will emit this event // BadBlock is called When blockchain declines a block, it will emit a new block event
BadBlock
// BadHeader is called When blockchain rejects a Header, it will emit this event
BadHeader
) )
// Event represents a new Event that a subscriber can listen to
type Event struct { type Event struct {
Type EventType // E.g. event.NewBlock Type EventType // E.g. event.NewBlock
data []byte // Raw information data []byte // Raw information

View file

@ -1,5 +1,6 @@
package pubsub package pubsub
// Publisher sends events to subscribers
type Publisher struct { type Publisher struct {
subs []Subscriber subs []Subscriber
} }

View file

@ -1,5 +1,6 @@
package pubsub package pubsub
// Subscriber will listen for Events from publishers
type Subscriber interface { type Subscriber interface {
Topics() []EventType Topics() []EventType
Emit(Event) Emit(Event)

View file

@ -8,7 +8,6 @@ import (
) )
// Base is everything in the message except the payload // Base is everything in the message except the payload
type Base struct { type Base struct {
Magic uint32 Magic uint32
CMD command.Type CMD command.Type
@ -16,9 +15,8 @@ type Base struct {
Checksum uint32 Checksum uint32
} }
// Note, That there is no EncodeBase // DecodeBase will decode an io.Reader into a Base object
// As the header is implicitly inferred from // Note, That there is no EncodeBase, As the header is implicitly inferred from the message on Encode To send
// the message on Encode To send
func (h *Base) DecodeBase(r io.Reader) (io.Reader, error) { func (h *Base) DecodeBase(r io.Reader) (io.Reader, error) {
br := &util.BinReader{R: r} br := &util.BinReader{R: r}

View file

@ -5,11 +5,10 @@ const (
Size = 12 Size = 12
) )
// CommandType represents the type of a message command. // Type represents the type of a message command.
type Type string type Type string
// Valid protocol commands used to send between nodes. // Valid protocol commands used to send between nodes.
// use this to get
const ( const (
Version Type = "version" Version Type = "version"
Mempool Type = "mempool" Mempool Type = "mempool"

View file

@ -15,9 +15,15 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// Messager is implemented by any object that can
// Encode and Decode Payloads
type Messager interface { type Messager interface {
// EncodePayload takes a message payload and encodes it
EncodePayload(w io.Writer) error EncodePayload(w io.Writer) error
// DecodePayload takes an io.Reader and decodes it into
// a message payload
DecodePayload(r io.Reader) error DecodePayload(r io.Reader) error
// Command returns the assosciated command type
Command() command.Type Command() command.Type
} }
@ -30,6 +36,7 @@ var (
errChecksumMismatch = errors.New("checksum mismatch") errChecksumMismatch = errors.New("checksum mismatch")
) )
// WriteMessage will write a message to a given io.Writer
func WriteMessage(w io.Writer, magic protocol.Magic, message Messager) error { func WriteMessage(w io.Writer, magic protocol.Magic, message Messager) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
bw.Write(magic) bw.Write(magic)
@ -51,6 +58,7 @@ func WriteMessage(w io.Writer, magic protocol.Magic, message Messager) error {
return bw.Err return bw.Err
} }
// ReadMessage will read a message from a given io.Reader
func ReadMessage(r io.Reader, magic protocol.Magic) (Messager, error) { func ReadMessage(r io.Reader, magic protocol.Magic) (Messager, error) {
byt := make([]byte, minMsgSize) byt := make([]byte, minMsgSize)
@ -122,7 +130,7 @@ func ReadMessage(r io.Reader, magic protocol.Magic) (Messager, error) {
return v, err return v, err
case command.TX: case command.TX:
reader := bufio.NewReader(buf) reader := bufio.NewReader(buf)
tx, err := transaction.FromBytes(reader) tx, err := transaction.FromReader(reader)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -9,21 +9,27 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// Block representa a Block in the neo-network
type Block struct { type Block struct {
BlockBase BlockBase
Txs []transaction.Transactioner Txs []transaction.Transactioner
} }
// Decode decodes an io.Reader into a Block
func (b *Block) Decode(r io.Reader) error { func (b *Block) Decode(r io.Reader) error {
br := &util.BinReader{R: r} br := &util.BinReader{R: r}
b.DecodePayload(br) b.DecodePayload(br)
return br.Err return br.Err
} }
// Encode writes a block into a io.Writer
func (b *Block) Encode(w io.Writer) error { func (b *Block) Encode(w io.Writer) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
b.EncodePayload(bw) b.EncodePayload(bw)
return bw.Err return bw.Err
} }
//EncodePayload implements Messager interface
func (b *Block) EncodePayload(bw *util.BinWriter) { func (b *Block) EncodePayload(bw *util.BinWriter) {
b.BlockBase.EncodePayload(bw) b.BlockBase.EncodePayload(bw)
bw.VarUint(uint64(len(b.Txs))) bw.VarUint(uint64(len(b.Txs)))
@ -32,6 +38,7 @@ func (b *Block) EncodePayload(bw *util.BinWriter) {
} }
} }
// DecodePayload implements Messager interface
func (b *Block) DecodePayload(br *util.BinReader) error { func (b *Block) DecodePayload(br *util.BinReader) error {
b.BlockBase.DecodePayload(br) b.BlockBase.DecodePayload(br)
@ -42,7 +49,7 @@ func (b *Block) DecodePayload(br *util.BinReader) error {
reader := bufio.NewReader(br.R) reader := bufio.NewReader(br.R)
for i := 0; i < int(lenTXs); i++ { for i := 0; i < int(lenTXs); i++ {
tx, err := transaction.FromBytes(reader) tx, err := transaction.FromReader(reader)
if err != nil { if err != nil {
return err return err
} }
@ -52,6 +59,7 @@ func (b *Block) DecodePayload(br *util.BinReader) error {
return nil return nil
} }
// Bytes returns the Byte representation of Block
func (b *Block) Bytes() ([]byte, error) { func (b *Block) Bytes() ([]byte, error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
err := b.Encode(buf) err := b.Encode(buf)

View file

@ -10,9 +10,11 @@ import (
) )
var ( var (
ErrPadding = errors.New("There is a padding mismatch") errPadding = errors.New("There is a padding mismatch")
) )
//BlockBase represents the base of the block
// This is different than the block header. See HeadersMessage
type BlockBase struct { type BlockBase struct {
// Version of the block. // Version of the block.
Version uint32 `json:"version"` Version uint32 `json:"version"`
@ -47,6 +49,7 @@ type BlockBase struct {
Hash util.Uint256 Hash util.Uint256
} }
// EncodePayload implements the Messager interface
func (b *BlockBase) EncodePayload(bw *util.BinWriter) error { func (b *BlockBase) EncodePayload(bw *util.BinWriter) error {
b.encodeHashableFields(bw) b.encodeHashableFields(bw)
@ -57,11 +60,14 @@ func (b *BlockBase) EncodePayload(bw *util.BinWriter) error {
return bw.Err return bw.Err
} }
// Decode decodes an io.Reader into a Blockbase
func (b *BlockBase) Decode(r io.Reader) error { func (b *BlockBase) Decode(r io.Reader) error {
br := &util.BinReader{R: r} br := &util.BinReader{R: r}
b.DecodePayload(br) b.DecodePayload(br)
return br.Err return br.Err
} }
// Encode encodes a blockbase into an io.Writer
func (b *BlockBase) Encode(w io.Writer) error { func (b *BlockBase) Encode(w io.Writer) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
b.EncodePayload(bw) b.EncodePayload(bw)
@ -78,6 +84,7 @@ func (b *BlockBase) encodeHashableFields(bw *util.BinWriter) {
bw.Write(b.NextConsensus) bw.Write(b.NextConsensus)
} }
// DecodePayload implements the messager interface
func (b *BlockBase) DecodePayload(br *util.BinReader) error { func (b *BlockBase) DecodePayload(br *util.BinReader) error {
b.decodeHashableFields(br) b.decodeHashableFields(br)
@ -85,7 +92,7 @@ func (b *BlockBase) DecodePayload(br *util.BinReader) error {
var padding uint8 var padding uint8
br.Read(&padding) br.Read(&padding)
if padding != 1 { if padding != 1 {
return ErrPadding return errPadding
} }
b.Witness = transaction.Witness{} b.Witness = transaction.Witness{}
@ -117,6 +124,7 @@ func (b *BlockBase) createHash() error {
return err return err
} }
// Bytes returns the byte representation of Blockbase
func (b *BlockBase) Bytes() ([]byte, error) { func (b *BlockBase) Bytes() ([]byte, error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
err := b.Encode(buf) err := b.Encode(buf)

View file

@ -7,10 +7,12 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// AddrMessage represents an address message on the neo network
type AddrMessage struct { type AddrMessage struct {
AddrList []*Net_addr AddrList []*NetAddr
} }
// NewAddrMessage instantiates a new AddrMessage
func NewAddrMessage() (*AddrMessage, error) { func NewAddrMessage() (*AddrMessage, error) {
addrMess := &AddrMessage{ addrMess := &AddrMessage{
nil, nil,
@ -18,22 +20,23 @@ func NewAddrMessage() (*AddrMessage, error) {
return addrMess, nil return addrMess, nil
} }
func (a *AddrMessage) AddNetAddr(n *Net_addr) error { // AddNetAddr will add a net address into the Address message
func (a *AddrMessage) AddNetAddr(n *NetAddr) error {
a.AddrList = append(a.AddrList, n) a.AddrList = append(a.AddrList, n)
// TODO:check if max reached, if so return err. What is max? // TODO:check if max reached, if so return err. What is max?
return nil return nil
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (a *AddrMessage) DecodePayload(r io.Reader) error { func (a *AddrMessage) DecodePayload(r io.Reader) error {
br := &util.BinReader{R: r} br := &util.BinReader{R: r}
listLen := br.VarUint() listLen := br.VarUint()
a.AddrList = make([]*Net_addr, listLen) a.AddrList = make([]*NetAddr, listLen)
for i := 0; i < int(listLen); i++ { for i := 0; i < int(listLen); i++ {
a.AddrList[i] = &Net_addr{} a.AddrList[i] = &NetAddr{}
a.AddrList[i].DecodePayload(br) a.AddrList[i].DecodePayload(br)
if br.Err != nil { if br.Err != nil {
return br.Err return br.Err
@ -42,20 +45,20 @@ func (a *AddrMessage) DecodePayload(r io.Reader) error {
return br.Err return br.Err
} }
// Implements messager interface // EncodePayload Implements messager interface
func (v *AddrMessage) EncodePayload(w io.Writer) error { func (a *AddrMessage) EncodePayload(w io.Writer) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
listLen := uint64(len(v.AddrList)) listLen := uint64(len(a.AddrList))
bw.VarUint(listLen) bw.VarUint(listLen)
for _, addr := range v.AddrList { for _, addr := range a.AddrList {
addr.EncodePayload(bw) addr.EncodePayload(bw)
} }
return bw.Err return bw.Err
} }
// Implements messager interface // Command Implements messager interface
func (v *AddrMessage) Command() command.Type { func (a *AddrMessage) Command() command.Type {
return command.Addr return command.Addr
} }

View file

@ -8,29 +8,31 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/command" "github.com/CityOfZion/neo-go/pkg/wire/command"
) )
// BlockMessage represents a block message on the neo-network
type BlockMessage struct { type BlockMessage struct {
Block Block
} }
// NewBlockMessage will return a block message object
func NewBlockMessage() (*BlockMessage, error) { func NewBlockMessage() (*BlockMessage, error) {
return &BlockMessage{}, nil return &BlockMessage{}, nil
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (b *BlockMessage) DecodePayload(r io.Reader) error { func (b *BlockMessage) DecodePayload(r io.Reader) error {
br := &util.BinReader{R: r} br := &util.BinReader{R: r}
b.Block.DecodePayload(br) b.Block.DecodePayload(br)
return br.Err return br.Err
} }
// Implements messager interface // EncodePayload Implements messager interface
func (b *BlockMessage) EncodePayload(w io.Writer) error { func (b *BlockMessage) EncodePayload(w io.Writer) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
b.Block.EncodePayload(bw) b.Block.EncodePayload(bw)
return bw.Err return bw.Err
} }
// Implements messager interface // Command Implements messager interface
func (v *BlockMessage) Command() command.Type { func (b *BlockMessage) Command() command.Type {
return command.Block return command.Block
} }

View file

@ -6,24 +6,25 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/command" "github.com/CityOfZion/neo-go/pkg/wire/command"
) )
// No payload //GetAddrMessage represents a GetAddress message on the neo-network
type GetAddrMessage struct{} type GetAddrMessage struct{}
// NewGetAddrMessage returns a GetAddrMessage object
func NewGetAddrMessage() (*GetAddrMessage, error) { func NewGetAddrMessage() (*GetAddrMessage, error) {
return &GetAddrMessage{}, nil return &GetAddrMessage{}, nil
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (v *GetAddrMessage) DecodePayload(r io.Reader) error { func (v *GetAddrMessage) DecodePayload(r io.Reader) error {
return nil return nil
} }
// Implements messager interface // EncodePayload Implements messager interface
func (v *GetAddrMessage) EncodePayload(w io.Writer) error { func (v *GetAddrMessage) EncodePayload(w io.Writer) error {
return nil return nil
} }
// Implements messager interface // Command Implements messager interface
func (v *GetAddrMessage) Command() command.Type { func (v *GetAddrMessage) Command() command.Type {
return command.GetAddr return command.GetAddr
} }

View file

@ -5,10 +5,12 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// GetBlocksMessage represnts a GetBlocks message on the neo-network
type GetBlocksMessage struct { type GetBlocksMessage struct {
*GetHeadersMessage *GetHeadersMessage
} }
// NewGetBlocksMessage returns a GetBlocksMessage object
func NewGetBlocksMessage(start []util.Uint256, stop util.Uint256) (*GetBlocksMessage, error) { func NewGetBlocksMessage(start []util.Uint256, stop util.Uint256) (*GetBlocksMessage, error) {
GetHeaders, err := newAbstractGetHeaders(start, stop, command.GetBlocks) GetHeaders, err := newAbstractGetHeaders(start, stop, command.GetBlocks)

View file

@ -4,10 +4,12 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/command" "github.com/CityOfZion/neo-go/pkg/wire/command"
) )
// GetDataMessage represents a GetData message on the neo-network
type GetDataMessage struct { type GetDataMessage struct {
*InvMessage *InvMessage
} }
//NewGetDataMessage returns a GetDataMessage object
func NewGetDataMessage(typ InvType) (*GetDataMessage, error) { func NewGetDataMessage(typ InvType) (*GetDataMessage, error) {
getData, err := newAbstractInv(typ, command.GetData) getData, err := newAbstractInv(typ, command.GetData)
return &GetDataMessage{ return &GetDataMessage{

View file

@ -7,12 +7,14 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
//GetHeadersMessage represents a GetHeaders message on the neo-network
type GetHeadersMessage struct { type GetHeadersMessage struct {
cmd command.Type cmd command.Type
hashStart []util.Uint256 hashStart []util.Uint256
hashStop util.Uint256 hashStop util.Uint256
} }
// NewGetHeadersMessage returns a NewGetHeaders object
// Start contains the list of all headers you want to fetch // Start contains the list of all headers you want to fetch
// End contains the list of the highest header hash you would like to fetch // End contains the list of the highest header hash you would like to fetch
func NewGetHeadersMessage(start []util.Uint256, stop util.Uint256) (*GetHeadersMessage, error) { func NewGetHeadersMessage(start []util.Uint256, stop util.Uint256) (*GetHeadersMessage, error) {
@ -32,7 +34,7 @@ func newAbstractGetHeaders(start []util.Uint256, stop util.Uint256, cmd command.
return getHeaders, nil return getHeaders, nil
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (v *GetHeadersMessage) DecodePayload(r io.Reader) error { func (v *GetHeadersMessage) DecodePayload(r io.Reader) error {
br := util.BinReader{R: r} br := util.BinReader{R: r}
@ -44,7 +46,7 @@ func (v *GetHeadersMessage) DecodePayload(r io.Reader) error {
return br.Err return br.Err
} }
// Implements messager interface // EncodePayload Implements messager interface
func (v *GetHeadersMessage) EncodePayload(w io.Writer) error { func (v *GetHeadersMessage) EncodePayload(w io.Writer) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
bw.VarUint(uint64(len(v.hashStart))) bw.VarUint(uint64(len(v.hashStart)))
@ -53,7 +55,7 @@ func (v *GetHeadersMessage) EncodePayload(w io.Writer) error {
return bw.Err return bw.Err
} }
// Implements messager interface // Command Implements messager interface
func (v *GetHeadersMessage) Command() command.Type { func (v *GetHeadersMessage) Command() command.Type {
return v.cmd return v.cmd
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// HeadersMessage represents a Header(s) Message on the neo-network
type HeadersMessage struct { type HeadersMessage struct {
Headers []*BlockBase Headers []*BlockBase
@ -21,31 +22,34 @@ const (
) )
var ( var (
ErrMaxHeaders = errors.New("Maximum amount of headers allowed is 2000") errMaxHeaders = errors.New("Maximum amount of headers allowed is 2000")
) )
//NewHeadersMessage returns a HeadersMessage Object
func NewHeadersMessage() (*HeadersMessage, error) { func NewHeadersMessage() (*HeadersMessage, error) {
headers := &HeadersMessage{nil, 0} headers := &HeadersMessage{nil, 0}
return headers, nil return headers, nil
} }
// AddHeader adds a header into the list of Headers.
// Since a header is just blockbase with padding, we use BlockBase
func (h *HeadersMessage) AddHeader(head *BlockBase) error { func (h *HeadersMessage) AddHeader(head *BlockBase) error {
if len(h.Headers)+1 > maxHeadersAllowed { if len(h.Headers)+1 > maxHeadersAllowed {
return ErrMaxHeaders return errMaxHeaders
} }
h.Headers = append(h.Headers, head) h.Headers = append(h.Headers, head)
return nil return nil
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (v *HeadersMessage) DecodePayload(r io.Reader) error { func (h *HeadersMessage) DecodePayload(r io.Reader) error {
br := &util.BinReader{R: r} br := &util.BinReader{R: r}
lenHeaders := br.VarUint() lenHeaders := br.VarUint()
v.Headers = make([]*BlockBase, lenHeaders) h.Headers = make([]*BlockBase, lenHeaders)
for i := 0; i < int(lenHeaders); i++ { for i := 0; i < int(lenHeaders); i++ {
header := &BlockBase{} header := &BlockBase{}
@ -53,26 +57,26 @@ func (v *HeadersMessage) DecodePayload(r io.Reader) error {
var padding uint8 var padding uint8
br.Read(&padding) br.Read(&padding)
if padding != 0 { if padding != 0 {
return ErrPadding return errPadding
} }
v.Headers[i] = header h.Headers[i] = header
} }
return br.Err return br.Err
} }
// Implements messager interface // EncodePayload Implements messager interface
func (v *HeadersMessage) EncodePayload(w io.Writer) error { func (h *HeadersMessage) EncodePayload(w io.Writer) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
bw.VarUint(uint64(len(v.Headers))) bw.VarUint(uint64(len(h.Headers)))
for _, header := range v.Headers { for _, header := range h.Headers {
header.EncodePayload(bw) header.EncodePayload(bw)
bw.Write(uint8(0)) bw.Write(uint8(0))
} }
return bw.Err return bw.Err
} }
// Implements messager interface // Command Implements messager interface
func (v *HeadersMessage) Command() command.Type { func (h *HeadersMessage) Command() command.Type {
return command.Headers return command.Headers
} }

View file

@ -8,29 +8,30 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
//InvType represents the enum of inventory types
type InvType uint8 type InvType uint8
//Inventory types
const ( const (
// InvTypeTx represents the transaction inventory type
InvTypeTx InvType = 0x01 InvTypeTx InvType = 0x01
// InvTypeBlock represents the block inventory type
InvTypeBlock InvType = 0x02 InvTypeBlock InvType = 0x02
// InvTypeConsensus represents the consensus inventory type
InvTypeConsensus InvType = 0xe0 InvTypeConsensus InvType = 0xe0
) )
const ( const maxHashes = 0x10000000
maxHashes = 0x10000000
)
var ( var errMaxHash = errors.New("max size For Hashes reached")
MaxHashError = errors.New("Max size For Hashes reached")
)
// InvMessage represents an Inventory message on the neo-network
type InvMessage struct { type InvMessage struct {
cmd command.Type cmd command.Type
Type InvType Type InvType
Hashes []util.Uint256 Hashes []util.Uint256
} }
//NewInvMessage returns an InvMessage object
func NewInvMessage(typ InvType) (*InvMessage, error) { func NewInvMessage(typ InvType) (*InvMessage, error) {
inv := &InvMessage{ inv := &InvMessage{
@ -53,17 +54,20 @@ func newAbstractInv(typ InvType, cmd command.Type) (*InvMessage, error) {
} }
func (i *InvMessage) AddHash(h util.Uint256) error { // AddHash adds a hash to the list of hashes
if len(i.Hashes)+1 > maxHashes { func (inv *InvMessage) AddHash(h util.Uint256) error {
return MaxHashError if len(inv.Hashes)+1 > maxHashes {
return errMaxHash
} }
i.Hashes = append(i.Hashes, h) inv.Hashes = append(inv.Hashes, h)
return nil return nil
} }
func (i *InvMessage) AddHashes(hashes []util.Uint256) error {
// AddHashes adds multiple hashes to the list of hashes
func (inv *InvMessage) AddHashes(hashes []util.Uint256) error {
var err error var err error
for _, hash := range hashes { for _, hash := range hashes {
err = i.AddHash(hash) err = inv.AddHash(hash)
if err != nil { if err != nil {
break break
} }
@ -71,31 +75,31 @@ func (i *InvMessage) AddHashes(hashes []util.Uint256) error {
return err return err
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (v *InvMessage) DecodePayload(r io.Reader) error { func (inv *InvMessage) DecodePayload(r io.Reader) error {
br := &util.BinReader{R: r} br := &util.BinReader{R: r}
br.Read(&v.Type) br.Read(&inv.Type)
listLen := br.VarUint() listLen := br.VarUint()
v.Hashes = make([]util.Uint256, listLen) inv.Hashes = make([]util.Uint256, listLen)
for i := 0; i < int(listLen); i++ { for i := 0; i < int(listLen); i++ {
br.Read(&v.Hashes[i]) br.Read(&inv.Hashes[i])
} }
return nil return nil
} }
// Implements messager interface // EncodePayload Implements messager interface
func (v *InvMessage) EncodePayload(w io.Writer) error { func (inv *InvMessage) EncodePayload(w io.Writer) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
bw.Write(v.Type) bw.Write(inv.Type)
lenhashes := len(v.Hashes) lenhashes := len(inv.Hashes)
bw.VarUint(uint64(lenhashes)) bw.VarUint(uint64(lenhashes))
for _, hash := range v.Hashes { for _, hash := range inv.Hashes {
bw.Write(hash) bw.Write(hash)
@ -104,7 +108,7 @@ func (v *InvMessage) EncodePayload(w io.Writer) error {
return bw.Err return bw.Err
} }
// Implements messager interface // Command Implements messager interface
func (v *InvMessage) Command() command.Type { func (inv *InvMessage) Command() command.Type {
return v.cmd return inv.cmd
} }

View file

@ -6,24 +6,25 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/command" "github.com/CityOfZion/neo-go/pkg/wire/command"
) )
// No payload // GetMempool represents a GetMempool message on the neo-network
type GetMempool struct{} type GetMempool struct{}
//NewGetMempool returns a GetMempool message
func NewGetMempool() (*GetMempool, error) { func NewGetMempool() (*GetMempool, error) {
return &GetMempool{}, nil return &GetMempool{}, nil
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (v *GetMempool) DecodePayload(r io.Reader) error { func (v *GetMempool) DecodePayload(r io.Reader) error {
return nil return nil
} }
// Implements messager interface // EncodePayload Implements messager interface
func (v *GetMempool) EncodePayload(w io.Writer) error { func (v *GetMempool) EncodePayload(w io.Writer) error {
return nil return nil
} }
// Implements messager interface // Command Implements messager interface
func (v *GetMempool) Command() command.Type { func (v *GetMempool) Command() command.Type {
return command.Mempool return command.Mempool
} }

View file

@ -7,28 +7,29 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction" "github.com/CityOfZion/neo-go/pkg/wire/payload/transaction"
) )
// TXMessage represents a transaction message on the neo-network
type TXMessage struct { type TXMessage struct {
// w *bytes.Buffer
Tx transaction.Transactioner Tx transaction.Transactioner
} }
//NewTXMessage returns a new tx object
func NewTXMessage(tx transaction.Transactioner) (*TXMessage, error) { func NewTXMessage(tx transaction.Transactioner) (*TXMessage, error) {
Tx := &TXMessage{tx} Tx := &TXMessage{tx}
return Tx, nil return Tx, nil
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (t *TXMessage) DecodePayload(r io.Reader) error { func (t *TXMessage) DecodePayload(r io.Reader) error {
return t.Tx.Decode(r) return t.Tx.Decode(r)
} }
// Implements messager interface // EncodePayload Implements messager interface
func (t *TXMessage) EncodePayload(w io.Writer) error { func (t *TXMessage) EncodePayload(w io.Writer) error {
return t.Tx.Encode(w) return t.Tx.Encode(w)
} }
// Implements messager interface // Command Implements messager interface
func (v *TXMessage) Command() command.Type { func (t *TXMessage) Command() command.Type {
return command.TX return command.TX
} }

View file

@ -6,24 +6,25 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/command" "github.com/CityOfZion/neo-go/pkg/wire/command"
) )
// No payload //VerackMessage represents a verack message on the neo-network
type VerackMessage struct{} type VerackMessage struct{}
//NewVerackMessage returns a verack message
func NewVerackMessage() (*VerackMessage, error) { func NewVerackMessage() (*VerackMessage, error) {
return &VerackMessage{}, nil return &VerackMessage{}, nil
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (v *VerackMessage) DecodePayload(r io.Reader) error { func (v *VerackMessage) DecodePayload(r io.Reader) error {
return nil return nil
} }
// Implements messager interface // EncodePayload Implements messager interface
func (v *VerackMessage) EncodePayload(w io.Writer) error { func (v *VerackMessage) EncodePayload(w io.Writer) error {
return nil return nil
} }
// Implements messager interface // Command Implements messager interface
func (v *VerackMessage) Command() command.Type { func (v *VerackMessage) Command() command.Type {
return command.Verack return command.Verack
} }

View file

@ -13,15 +13,12 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
const ( const minMsgVersionSize = 28
minMsgVersionSize = 28
)
// TODO: Refactor to pull out the useragent out of initialiser var errInvalidNetAddr = errors.New("provided net.Addr is not a net.TCPAddr")
// and have a seperate method to add it
//VersionMessage represents a version message on the neo-network
type VersionMessage struct { type VersionMessage struct {
// w *bytes.Buffer
Version protocol.Version Version protocol.Version
Timestamp uint32 Timestamp uint32
Services protocol.ServiceFlag Services protocol.ServiceFlag
@ -33,13 +30,12 @@ type VersionMessage struct {
Relay bool Relay bool
} }
var ErrInvalidNetAddr = errors.New("provided net.Addr is not a net.TCPAddr") //NewVersionMessage will return a VersionMessage object
func NewVersionMessage(addr net.Addr, startHeight uint32, relay bool, pver protocol.Version, userAgent string, nonce uint32, services protocol.ServiceFlag) (*VersionMessage, error) { func NewVersionMessage(addr net.Addr, startHeight uint32, relay bool, pver protocol.Version, userAgent string, nonce uint32, services protocol.ServiceFlag) (*VersionMessage, error) {
tcpAddr, ok := addr.(*net.TCPAddr) tcpAddr, ok := addr.(*net.TCPAddr)
if !ok { if !ok {
return nil, ErrInvalidNetAddr return nil, errInvalidNetAddr
} }
version := &VersionMessage{ version := &VersionMessage{
@ -56,13 +52,13 @@ func NewVersionMessage(addr net.Addr, startHeight uint32, relay bool, pver proto
return version, nil return version, nil
} }
// Implements Messager interface // DecodePayload Implements Messager interface
func (v *VersionMessage) DecodePayload(r io.Reader) error { func (v *VersionMessage) DecodePayload(r io.Reader) error {
br := &util.BinReader{R: r} br := &util.BinReader{R: r}
br.Read(&v.Version) br.Read(&v.Version)
br.Read(&v.Services) br.Read(&v.Services)
br.Read(&v.Timestamp) br.Read(&v.Timestamp)
br.Read(&v.Port) // Port is not BigEndian br.Read(&v.Port) // Port is not BigEndian as stated in the docs
br.Read(&v.Nonce) br.Read(&v.Nonce)
var lenUA uint8 var lenUA uint8
@ -75,7 +71,7 @@ func (v *VersionMessage) DecodePayload(r io.Reader) error {
return br.Err return br.Err
} }
// Implements messager interface // EncodePayload Implements messager interface
func (v *VersionMessage) EncodePayload(w io.Writer) error { func (v *VersionMessage) EncodePayload(w io.Writer) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
@ -91,7 +87,7 @@ func (v *VersionMessage) EncodePayload(w io.Writer) error {
return bw.Err return bw.Err
} }
// Implements messager interface // Command Implements messager interface
func (v *VersionMessage) Command() command.Type { func (v *VersionMessage) Command() command.Type {
return command.Version return command.Version
} }

View file

@ -9,21 +9,21 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// Once a VersionMessage is received, we can then store it inside of AddrMessage struct //NetAddr is an abstraction for the IP layer
// TODO: store this inside version message and have a bool to indicate whether to encode ip type NetAddr struct {
// VersionMessage does not encodeIP
type Net_addr struct {
Timestamp uint32 Timestamp uint32
IP [16]byte IP [16]byte
Port uint16 Port uint16
Service protocol.ServiceFlag Service protocol.ServiceFlag
} }
func NewNetAddr(time uint32, ip [16]byte, port uint16, service protocol.ServiceFlag) (*Net_addr, error) { //NewNetAddr returns a NetAddr object
return &Net_addr{time, ip, port, service}, nil func NewNetAddr(time uint32, ip [16]byte, port uint16, service protocol.ServiceFlag) (*NetAddr, error) {
return &NetAddr{time, ip, port, service}, nil
} }
func NewAddrFromVersionMessage(version VersionMessage) (*Net_addr, error) { //NewAddrFromVersionMessage returns a NetAddr object from a version message
func NewAddrFromVersionMessage(version VersionMessage) (*NetAddr, error) {
var ip [16]byte var ip [16]byte
@ -32,21 +32,26 @@ func NewAddrFromVersionMessage(version VersionMessage) (*Net_addr, error) {
return NewNetAddr(version.Timestamp, ip, version.Port, version.Services) return NewNetAddr(version.Timestamp, ip, version.Port, version.Services)
} }
func (n *Net_addr) EncodePayload(bw *util.BinWriter) { // EncodePayload Implements messager interface
func (n *NetAddr) EncodePayload(bw *util.BinWriter) {
bw.Write(uint32(time.Now().Unix())) bw.Write(uint32(time.Now().Unix()))
bw.Write(protocol.NodePeerService) bw.Write(protocol.NodePeerService)
bw.WriteBigEnd(n.IP) bw.WriteBigEnd(n.IP)
bw.WriteBigEnd(n.Port) bw.WriteBigEnd(n.Port)
} }
func (n *Net_addr) DecodePayload(br *util.BinReader) {
// DecodePayload Implements Messager interface
func (n *NetAddr) DecodePayload(br *util.BinReader) {
br.Read(&n.Timestamp) br.Read(&n.Timestamp)
br.Read(&n.Service) br.Read(&n.Service)
br.ReadBigEnd(&n.IP) br.ReadBigEnd(&n.IP)
br.ReadBigEnd(&n.Port) br.ReadBigEnd(&n.Port)
} }
func (n *Net_addr) IPPort() string {
//IPPort returns the IPPort from the NetAddr
func (n *NetAddr) IPPort() string {
ip := net.IP(n.IP[:]).String() ip := net.IP(n.IP[:]).String()
port := strconv.Itoa(int(n.Port)) port := strconv.Itoa(int(n.Port))
ipport := ip + ":" + port ipport := ip + ":" + port

View file

@ -12,17 +12,14 @@ type Attribute struct {
Data []byte Data []byte
} }
var ( var errMaxData = errors.New("max Size of Attribute reached")
ErrMaxData = errors.New("Max Size of Attribute reached")
)
const ( const maxAttrSize = 65535
maxAttrSize = 65535
)
// Encode encodes the given Attribute into the binary writer
func (a *Attribute) Encode(bw *util.BinWriter) { func (a *Attribute) Encode(bw *util.BinWriter) {
if len(a.Data) > maxAttrSize { if len(a.Data) > maxAttrSize {
bw.Err = ErrMaxData bw.Err = errMaxData
return return
} }
bw.Write(uint8(a.Usage)) bw.Write(uint8(a.Usage))
@ -43,6 +40,7 @@ func (a *Attribute) Encode(bw *util.BinWriter) {
} }
// Decode decodes the binary reader into an Attribute object
func (a *Attribute) Decode(br *util.BinReader) { func (a *Attribute) Decode(br *util.BinReader) {
br.Read(&a.Usage) br.Read(&a.Usage)
if a.Usage == DescriptionURL || a.Usage == Vote || a.Usage >= Hash1 && a.Usage <= Hash15 { if a.Usage == DescriptionURL || a.Usage == Vote || a.Usage >= Hash1 && a.Usage <= Hash15 {

View file

@ -11,17 +11,21 @@ type Input struct {
PrevIndex uint16 PrevIndex uint16
} }
//NewInput returns a transaction input object
func NewInput(prevHash util.Uint256, prevIndex uint16) *Input { func NewInput(prevHash util.Uint256, prevIndex uint16) *Input {
return &Input{ return &Input{
prevHash, prevHash,
prevIndex, prevIndex,
} }
} }
// Encode encodes the given input into a binary writer
func (i *Input) Encode(bw *util.BinWriter) { func (i *Input) Encode(bw *util.BinWriter) {
bw.Write(i.PrevHash) bw.Write(i.PrevHash)
bw.Write(i.PrevIndex) bw.Write(i.PrevIndex)
} }
// Decode decodes a binary reader into an input object
func (i *Input) Decode(br *util.BinReader) { func (i *Input) Decode(br *util.BinReader) {
br.Read(&i.PrevHash) br.Read(&i.PrevHash)
br.Read(&i.PrevIndex) br.Read(&i.PrevIndex)

View file

@ -2,6 +2,7 @@ package transaction
import "github.com/CityOfZion/neo-go/pkg/wire/util" import "github.com/CityOfZion/neo-go/pkg/wire/util"
// Output represents a transaction output in the neo-network
type Output struct { type Output struct {
// The NEO asset id used in the transaction. // The NEO asset id used in the transaction.
AssetID util.Uint256 AssetID util.Uint256
@ -13,6 +14,7 @@ type Output struct {
ScriptHash util.Uint160 ScriptHash util.Uint160
} }
//NewOutput returns an output object
func NewOutput(assetID util.Uint256, Amount int64, ScriptHash util.Uint160) *Output { func NewOutput(assetID util.Uint256, Amount int64, ScriptHash util.Uint160) *Output {
return &Output{ return &Output{
assetID, assetID,
@ -21,12 +23,14 @@ func NewOutput(assetID util.Uint256, Amount int64, ScriptHash util.Uint160) *Out
} }
} }
// Encode encodes the Output into a binary writer
func (o *Output) Encode(bw *util.BinWriter) { func (o *Output) Encode(bw *util.BinWriter) {
bw.Write(o.AssetID) bw.Write(o.AssetID)
bw.Write(o.Amount) bw.Write(o.Amount)
bw.Write(o.ScriptHash) bw.Write(o.ScriptHash)
} }
// Decode decodes a binary reader into an output object
func (o *Output) Decode(br *util.BinReader) { func (o *Output) Decode(br *util.BinReader) {
br.Read(&o.AssetID) br.Read(&o.AssetID)
br.Read(&o.Amount) br.Read(&o.Amount)

View file

@ -4,11 +4,13 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
//Witness represents a Witness object in a neo transaction
type Witness struct { type Witness struct {
InvocationScript []byte InvocationScript []byte
VerificationScript []byte VerificationScript []byte
} }
// Encode encodes a Witness into a binary writer
func (s *Witness) Encode(bw *util.BinWriter) error { func (s *Witness) Encode(bw *util.BinWriter) error {
bw.VarUint(uint64(len(s.InvocationScript))) bw.VarUint(uint64(len(s.InvocationScript)))
@ -20,6 +22,7 @@ func (s *Witness) Encode(bw *util.BinWriter) error {
return bw.Err return bw.Err
} }
// Decode decodes a binary reader into a Witness object
func (s *Witness) Decode(br *util.BinReader) error { func (s *Witness) Decode(br *util.BinReader) error {
lenb := br.VarUint() lenb := br.VarUint()

View file

@ -1,5 +1,6 @@
package transaction package transaction
// AttrUsage represents an attribute usage on the neo network
type AttrUsage uint8 type AttrUsage uint8
// List of valid attribute usages. // List of valid attribute usages.

View file

@ -53,16 +53,20 @@ func createBaseTransaction(typ types.TX, ver version.TX) *Base {
} }
// Decode implements the transactioner interface
func (b *Base) Decode(r io.Reader) error { func (b *Base) Decode(r io.Reader) error {
br := &util.BinReader{R: r} br := &util.BinReader{R: r}
return b.DecodePayload(br) return b.DecodePayload(br)
} }
// Encode implements the transactioner interface
func (b *Base) Encode(w io.Writer) error { func (b *Base) Encode(w io.Writer) error {
bw := &util.BinWriter{W: w} bw := &util.BinWriter{W: w}
b.EncodePayload(bw) b.EncodePayload(bw)
return bw.Err return bw.Err
} }
//EncodePayload implements the Messager interface
func (b *Base) EncodePayload(bw *util.BinWriter) { func (b *Base) EncodePayload(bw *util.BinWriter) {
b.encodeHashableFields(bw) b.encodeHashableFields(bw)
@ -74,6 +78,7 @@ func (b *Base) EncodePayload(bw *util.BinWriter) {
} }
} }
// DecodePayload implements the messager interface
func (b *Base) DecodePayload(br *util.BinReader) error { func (b *Base) DecodePayload(br *util.BinReader) error {
b.decodeHashableFields(br) b.decodeHashableFields(br)
@ -118,7 +123,6 @@ func (b *Base) encodeHashableFields(bw *util.BinWriter) {
} }
} }
// created for consistency
func (b *Base) decodeHashableFields(br *util.BinReader) { func (b *Base) decodeHashableFields(br *util.BinReader) {
b.Type.Decode(br) b.Type.Decode(br)
@ -151,15 +155,22 @@ func (b *Base) decodeHashableFields(br *util.BinReader) {
} }
// AddInput adds an input to the transaction
func (b *Base) AddInput(i *Input) { func (b *Base) AddInput(i *Input) {
b.Inputs = append(b.Inputs, i) b.Inputs = append(b.Inputs, i)
} }
// AddOutput adds an output to the transaction
func (b *Base) AddOutput(o *Output) { func (b *Base) AddOutput(o *Output) {
b.Outputs = append(b.Outputs, o) b.Outputs = append(b.Outputs, o)
} }
// AddAttribute adds an attribute to the transaction
func (b *Base) AddAttribute(a *Attribute) { func (b *Base) AddAttribute(a *Attribute) {
b.Attributes = append(b.Attributes, a) b.Attributes = append(b.Attributes, a)
} }
// AddWitness adds a witness object to the transaction
func (b *Base) AddWitness(w *Witness) { func (b *Base) AddWitness(w *Witness) {
b.Witnesses = append(b.Witnesses, w) b.Witnesses = append(b.Witnesses, w)
} }

View file

@ -6,11 +6,13 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
//Claim represents a claim transaction on the neo network
type Claim struct { type Claim struct {
*Base *Base
Claims []*Input Claims []*Input
} }
//NewClaim returns a ClaimTransaction
func NewClaim(ver version.TX) *Claim { func NewClaim(ver version.TX) *Claim {
basicTrans := createBaseTransaction(types.Contract, ver) basicTrans := createBaseTransaction(types.Contract, ver)
@ -39,5 +41,3 @@ func (c *Claim) decodeExcl(br *util.BinReader) {
} }
} }
// use encode and decode exclusive to make the interface

View file

@ -6,10 +6,12 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
//Contract represents a contract transaction on the neo network
type Contract struct { type Contract struct {
*Base *Base
} }
//NewContract returns a contract transaction
func NewContract(ver version.TX) *Contract { func NewContract(ver version.TX) *Contract {
basicTrans := createBaseTransaction(types.Contract, ver) basicTrans := createBaseTransaction(types.Contract, ver)
@ -21,10 +23,6 @@ func NewContract(ver version.TX) *Contract {
return contract return contract
} }
func (c *Contract) encodeExcl(bw *util.BinWriter) { func (c *Contract) encodeExcl(bw *util.BinWriter) {}
return
}
func (c *Contract) decodeExcl(br *util.BinReader) { func (c *Contract) decodeExcl(br *util.BinReader) {}
return
}

View file

@ -6,24 +6,26 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
//Enrollment represents an Enrollment transaction on the neo network
type Enrollment struct { type Enrollment struct {
*Base *Base
Key PublicKey Key PublicKey
} }
//NewEnrollment returns an Enrollment transaction
func NewEnrollment(ver version.TX) *Enrollment { func NewEnrollment(ver version.TX) *Enrollment {
basicTrans := createBaseTransaction(types.Enrollment, ver) basicTrans := createBaseTransaction(types.Enrollment, ver)
Enrollment := &Enrollment{} enrollment := &Enrollment{
Enrollment.Base = basicTrans Base: basicTrans,
Enrollment.encodeExclusive = Enrollment.encodeExcl }
Enrollment.decodeExclusive = Enrollment.decodeExcl enrollment.encodeExclusive = enrollment.encodeExcl
return Enrollment enrollment.decodeExclusive = enrollment.decodeExcl
return enrollment
} }
func (e *Enrollment) encodeExcl(bw *util.BinWriter) { func (e *Enrollment) encodeExcl(bw *util.BinWriter) {
e.Key.Encode(bw) e.Key.Encode(bw)
} }
func (e *Enrollment) decodeExcl(br *util.BinReader) { func (e *Enrollment) decodeExcl(br *util.BinReader) {

View file

@ -9,12 +9,14 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util/fixed8" "github.com/CityOfZion/neo-go/pkg/wire/util/fixed8"
) )
//Invocation represents an invocation transaction on the neo network
type Invocation struct { type Invocation struct {
*Base *Base
Script []byte Script []byte
Gas fixed8.Fixed8 Gas fixed8.Fixed8
} }
//NewInvocation returns an invocation transaction
func NewInvocation(ver version.TX) *Invocation { func NewInvocation(ver version.TX) *Invocation {
basicTrans := createBaseTransaction(types.Invocation, ver) basicTrans := createBaseTransaction(types.Invocation, ver)
@ -53,7 +55,7 @@ func (c *Invocation) decodeExcl(br *util.BinReader) {
case 1: case 1:
br.Read(&c.Gas) br.Read(&c.Gas)
default: default:
br.Err = errors.New("Invalid Version Number for Invocation Transaction") br.Err = errors.New("invalid Version Number for Invocation Transaction")
} }
return return
} }

View file

@ -8,10 +8,12 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// Issue represents an issue transaction on the neo network
type Issue struct { type Issue struct {
*Base *Base
} }
//NewIssue returns an issue transaction
func NewIssue(ver version.TX) *Issue { func NewIssue(ver version.TX) *Issue {
basicTrans := createBaseTransaction(types.Issue, ver) basicTrans := createBaseTransaction(types.Issue, ver)
@ -27,9 +29,6 @@ func (c *Issue) encodeExcl(bw *util.BinWriter) {
if c.Version > 1 { if c.Version > 1 {
bw.Err = errors.New("Version Number Invalid, Issue cannot be more than 0") bw.Err = errors.New("Version Number Invalid, Issue cannot be more than 0")
} }
return
} }
func (c *Issue) decodeExcl(br *util.BinReader) { func (c *Issue) decodeExcl(br *util.BinReader) {}
return
}

View file

@ -6,11 +6,13 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
//Miner represents a miner transaction on the neo network
type Miner struct { type Miner struct {
*Base *Base
Nonce uint32 Nonce uint32
} }
//NewMiner returns a miner transaction
func NewMiner(ver version.TX) *Miner { func NewMiner(ver version.TX) *Miner {
basicTrans := createBaseTransaction(types.Miner, ver) basicTrans := createBaseTransaction(types.Miner, ver)
@ -22,13 +24,9 @@ func NewMiner(ver version.TX) *Miner {
} }
func (c *Miner) encodeExcl(bw *util.BinWriter) { func (c *Miner) encodeExcl(bw *util.BinWriter) {
bw.Write(c.Nonce) bw.Write(c.Nonce)
return
} }
func (c *Miner) decodeExcl(br *util.BinReader) { func (c *Miner) decodeExcl(br *util.BinReader) {
br.Read(&c.Nonce) br.Read(&c.Nonce)
} }

View file

@ -6,13 +6,17 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// PublicKey represents a public key on the neo network
type PublicKey struct { type PublicKey struct {
Key []byte Key []byte
} }
//Encode encodes a public key into a binary writer
func (p *PublicKey) Encode(bw *util.BinWriter) { func (p *PublicKey) Encode(bw *util.BinWriter) {
bw.Write(p.Key) bw.Write(p.Key)
} }
// Decode decodes a bianry reader into a public key
func (p *PublicKey) Decode(br *util.BinReader) { func (p *PublicKey) Decode(br *util.BinReader) {
var prefix uint8 var prefix uint8
br.Read(&prefix) br.Read(&prefix)
@ -30,6 +34,5 @@ func (p *PublicKey) Decode(br *util.BinReader) {
br.Err = errors.New("Prefix not recognised for public key") br.Err = errors.New("Prefix not recognised for public key")
return return
} }
p.Key = append([]byte{prefix}, p.Key...) p.Key = append([]byte{prefix}, p.Key...)
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// Publish represents a publish transaction on the neo network
type Publish struct { type Publish struct {
*Base *Base
Script []byte Script []byte
@ -21,6 +22,7 @@ type Publish struct {
Description string Description string
} }
//NewPublish returns a publish transaction
func NewPublish(ver version.TX) *Publish { func NewPublish(ver version.TX) *Publish {
basicTrans := createBaseTransaction(types.Publish, ver) basicTrans := createBaseTransaction(types.Publish, ver)

View file

@ -7,6 +7,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util/fixed8" "github.com/CityOfZion/neo-go/pkg/wire/util/fixed8"
) )
// Register represents a register transaction on the neo network
type Register struct { type Register struct {
*Base *Base
// The type of the asset being registered. // The type of the asset being registered.
@ -28,6 +29,7 @@ type Register struct {
Admin util.Uint160 Admin util.Uint160
} }
//NewRegister returns a register transaction
func NewRegister(ver version.TX) *Register { func NewRegister(ver version.TX) *Register {
basicTrans := createBaseTransaction(types.Register, ver) basicTrans := createBaseTransaction(types.Register, ver)
Register := &Register{} Register := &Register{}

View file

@ -6,11 +6,14 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
//StateTX represents a state transaction on the neo network
// XXX: TX postfix here as `state` is ambiguous. We can remove it for consistency
type StateTX struct { type StateTX struct {
*Base *Base
Descriptors []*StateDescriptor Descriptors []*StateDescriptor
} }
//NewStateTX returns a state transaction
func NewStateTX(ver version.TX) *StateTX { func NewStateTX(ver version.TX) *StateTX {
basicTrans := createBaseTransaction(types.State, ver) basicTrans := createBaseTransaction(types.State, ver)

View file

@ -13,7 +13,8 @@ const (
Validator DescStateType = 0x48 Validator DescStateType = 0x48
) )
// StateDescriptor .. // StateDescriptor represents a state descriptor on the neo network
// used in a state transaction
type StateDescriptor struct { type StateDescriptor struct {
Type DescStateType Type DescStateType
Key []byte Key []byte
@ -21,6 +22,7 @@ type StateDescriptor struct {
Field string Field string
} }
// Decode decodes a binary reader into a state descriptor
func (s *StateDescriptor) Decode(br *util.BinReader) { func (s *StateDescriptor) Decode(br *util.BinReader) {
br.Read(&s.Type) br.Read(&s.Type)
@ -38,6 +40,8 @@ func (s *StateDescriptor) Decode(br *util.BinReader) {
s.Field = string(field) s.Field = string(field)
} }
//Encode encodes a state descriptor into a binary writer
func (s *StateDescriptor) Encode(bw *util.BinWriter) { func (s *StateDescriptor) Encode(bw *util.BinWriter) {
bw.Write(s.Type) bw.Write(s.Type)
@ -48,5 +52,4 @@ func (s *StateDescriptor) Encode(bw *util.BinWriter) {
bw.Write(s.Value) bw.Write(s.Value)
bw.VarString(s.Field) bw.VarString(s.Field)
} }

View file

@ -7,6 +7,7 @@ import (
// TX is the type of a transaction. // TX is the type of a transaction.
type TX uint8 type TX uint8
// List of transaction types
const ( const (
Miner TX = 0x00 Miner TX = 0x00
Issue TX = 0x01 Issue TX = 0x01
@ -21,9 +22,12 @@ const (
Invocation TX = 0xd1 Invocation TX = 0xd1
) )
// Encode encodes a tx type into the binary writer
func (t *TX) Encode(bw *util.BinWriter) { func (t *TX) Encode(bw *util.BinWriter) {
bw.Write(t) bw.Write(t)
} }
// Decode decodes a binary reader into a tx type
func (t *TX) Decode(br *util.BinReader) { func (t *TX) Decode(br *util.BinReader) {
br.Read(t) br.Read(t)
} }

View file

@ -8,7 +8,8 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types" "github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
) )
func FromBytes(reader *bufio.Reader) (Transactioner, error) { // FromReader returns a transaction from a bufio.Reader
func FromReader(reader *bufio.Reader) (Transactioner, error) {
t, err := reader.Peek(1) t, err := reader.Peek(1)
@ -45,17 +46,17 @@ func FromBytes(reader *bufio.Reader) (Transactioner, error) {
err = pub.Decode(reader) err = pub.Decode(reader)
trans = pub trans = pub
case types.State: case types.State:
sta := NewStateTX(0) state := NewStateTX(0)
err = sta.Decode(reader) err = state.Decode(reader)
trans = sta trans = state
case types.Enrollment: case types.Enrollment:
enr := NewEnrollment(0) enr := NewEnrollment(0)
err = enr.Decode(reader) err = enr.Decode(reader)
trans = enr trans = enr
case types.Agency: case types.Agency:
err = errors.New("Unsupported transaction type: Agency") err = errors.New("unsupported transaction type: Agency")
default: default:
err = errors.New("Unsupported transaction with byte type " + hex.EncodeToString([]byte{t[0]})) err = errors.New("unsupported transaction with byte type " + hex.EncodeToString([]byte{t[0]}))
} }
return trans, err return trans, err
} }

View file

@ -4,16 +4,21 @@ import (
"github.com/CityOfZion/neo-go/pkg/wire/util" "github.com/CityOfZion/neo-go/pkg/wire/util"
) )
// TX represents a tx version
type TX uint8 type TX uint8
// List of latest tx version
const ( const (
Contract TX = 0 Contract TX = 0
Invocation TX = 1
) )
// Encode encodes the tx version into the binary writer
func (v *TX) Encode(bw *util.BinWriter) { func (v *TX) Encode(bw *util.BinWriter) {
bw.Write(v) bw.Write(v)
} }
// Decode decodes the binary reader into a tx type
func (v *TX) Decode(br *util.BinReader) { func (v *TX) Decode(br *util.BinReader) {
br.Read(v) br.Read(v)
} }

View file

@ -1,15 +1,19 @@
package protocol package protocol
//Version represents the latest protocol version for the neo node
type Version uint32 type Version uint32
const ( const (
// DefaultVersion is the nodes default protocol version
DefaultVersion Version = 0 DefaultVersion Version = 0
UserAgent = "/NEO-GO/" // TODO: This may be relocated to a config file // UserAgent is the nodes user agent or human-readable name
UserAgent = "/NEO-GO/"
) )
// ServiceFlag indicates the services provided by the node. 1 = P2P Full Node // ServiceFlag indicates the services provided by the node. 1 = P2P Full Node
type ServiceFlag uint64 type ServiceFlag uint64
// List of Services offered by the node
const ( const (
NodePeerService ServiceFlag = 1 NodePeerService ServiceFlag = 1
// BloomFilerService ServiceFlag = 2 // Not implemented // BloomFilerService ServiceFlag = 2 // Not implemented
@ -21,6 +25,7 @@ const (
// Magic is the network that NEO is running on // Magic is the network that NEO is running on
type Magic uint32 type Magic uint32
// List of possible networks
const ( const (
MainNet Magic = 7630401 MainNet Magic = 7630401
TestNet Magic = 0x74746e41 TestNet Magic = 0x74746e41

View file

@ -7,16 +7,20 @@ import (
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
) )
// Compare calculates the checksum of b
// then compares it with the `have` checksum passed as a parameter
func Compare(have uint32, b []byte) bool { func Compare(have uint32, b []byte) bool {
want := FromBytes(b) want := FromBytes(b)
return have == want return have == want
} }
// FromBuf calculates the checksum of a buffer
func FromBuf(buf *bytes.Buffer) uint32 { func FromBuf(buf *bytes.Buffer) uint32 {
return FromBytes(buf.Bytes()) return FromBytes(buf.Bytes())
} }
// FromBytes calculates the checksum of a byte slice
func FromBytes(buf []byte) uint32 { func FromBytes(buf []byte) uint32 {
b, err := hash.DoubleSha256(buf) b, err := hash.DoubleSha256(buf)

View file

@ -6,6 +6,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/crypto/base58" "github.com/CityOfZion/neo-go/pkg/crypto/base58"
) )
// ToScriptHash converts an address to a script hash
func ToScriptHash(address string) string { func ToScriptHash(address string) string {
decodedAddressAsBytes, err := base58.Decode(address) decodedAddressAsBytes, err := base58.Decode(address)

View file

@ -5,17 +5,24 @@ import (
"io" "io"
) )
//BinReader is a convenient wrapper around a io.Reader and err object
// Used to simplify error handling when reading into a struct with many fields
type BinReader struct { type BinReader struct {
R io.Reader R io.Reader
Err error Err error
} }
// Read reads from the underlying io.Reader
// into the interface v in LE
func (r *BinReader) Read(v interface{}) { func (r *BinReader) Read(v interface{}) {
if r.Err != nil { if r.Err != nil {
return return
} }
r.Err = binary.Read(r.R, binary.LittleEndian, v) r.Err = binary.Read(r.R, binary.LittleEndian, v)
} }
// ReadBigEnd reads from the underlying io.Reader
// into the interface v in BE
func (r *BinReader) ReadBigEnd(v interface{}) { func (r *BinReader) ReadBigEnd(v interface{}) {
if r.Err != nil { if r.Err != nil {
return return
@ -23,6 +30,8 @@ func (r *BinReader) ReadBigEnd(v interface{}) {
r.Err = binary.Read(r.R, binary.BigEndian, v) r.Err = binary.Read(r.R, binary.BigEndian, v)
} }
//VarUint reads a variable integer from the
// underlying reader
func (r *BinReader) VarUint() uint64 { func (r *BinReader) VarUint() uint64 {
var b uint8 var b uint8
r.Err = binary.Read(r.R, binary.LittleEndian, &b) r.Err = binary.Read(r.R, binary.LittleEndian, &b)
@ -46,6 +55,8 @@ func (r *BinReader) VarUint() uint64 {
return uint64(b) return uint64(b)
} }
// VarBytes reads the next set of bytes from the underlying reader.
// VarUInt is used to determine how large that slice is
func (r *BinReader) VarBytes() []byte { func (r *BinReader) VarBytes() []byte {
n := r.VarUint() n := r.VarUint()
b := make([]byte, n) b := make([]byte, n)
@ -53,6 +64,7 @@ func (r *BinReader) VarBytes() []byte {
return b return b
} }
// VarString calls VarBytes and casts the results as a string
func (r *BinReader) VarString() string { func (r *BinReader) VarString() string {
b := r.VarBytes() b := r.VarBytes()
return string(b) return string(b)

View file

@ -6,11 +6,15 @@ import (
"io" "io"
) )
//BinWriter is a convenient wrapper around a io.Writer and err object
// Used to simplify error handling when writing into a io.Writer
// from a struct with many fields
type BinWriter struct { type BinWriter struct {
W io.Writer W io.Writer
Err error Err error
} }
// Write writes into the underlying io.Writer from an object v in LE format
func (w *BinWriter) Write(v interface{}) { func (w *BinWriter) Write(v interface{}) {
if w.Err != nil { if w.Err != nil {
return return
@ -18,6 +22,7 @@ func (w *BinWriter) Write(v interface{}) {
w.Err = binary.Write(w.W, binary.LittleEndian, v) w.Err = binary.Write(w.W, binary.LittleEndian, v)
} }
// WriteBigEnd writes into the underlying io.Writer from an object v in BE format
// Only used for IP and PORT. Additional method makes the default LittleEndian case clean // Only used for IP and PORT. Additional method makes the default LittleEndian case clean
func (w *BinWriter) WriteBigEnd(v interface{}) { func (w *BinWriter) WriteBigEnd(v interface{}) {
if w.Err != nil { if w.Err != nil {
@ -26,10 +31,7 @@ func (w *BinWriter) WriteBigEnd(v interface{}) {
w.Err = binary.Write(w.W, binary.BigEndian, v) w.Err = binary.Write(w.W, binary.BigEndian, v)
} }
func (w *BinWriter) VarString(s string) { // VarUint writes a uint64 into the underlying writer
w.VarBytes([]byte(s))
}
func (w *BinWriter) VarUint(val uint64) { func (w *BinWriter) VarUint(val uint64) {
if val < 0 { if val < 0 {
w.Err = errors.New("value out of range") w.Err = errors.New("value out of range")
@ -61,8 +63,13 @@ func (w *BinWriter) VarUint(val uint64) {
} }
// WriteVarBytes writes a variable length byte array. // VarBytes writes a variable length byte array into the underlying io.Writer
func (w *BinWriter) VarBytes(b []byte) { func (w *BinWriter) VarBytes(b []byte) {
w.VarUint(uint64(len(b))) w.VarUint(uint64(len(b)))
w.Write(b) w.Write(b)
} }
//VarString casts the string as a byte slice and calls VarBytes
func (w *BinWriter) VarString(s string) {
w.VarBytes([]byte(s))
}

View file

@ -1,8 +1,11 @@
package base58 package base58
import ( import (
"bytes"
"fmt" "fmt"
"math/big" "math/big"
"github.com/CityOfZion/neo-go/pkg/wire/util/crypto/hash"
) )
const prefix rune = '1' const prefix rune = '1'
@ -22,7 +25,7 @@ var decodeMap = map[rune]int64{
'x': 55, 'y': 56, 'z': 57, 'x': 55, 'y': 56, 'z': 57,
} }
// Base58Decode decodes the base58 encoded string. // Decode decodes the base58 encoded string.
func Decode(s string) ([]byte, error) { func Decode(s string) ([]byte, error) {
var ( var (
startIndex = 0 startIndex = 0
@ -58,7 +61,7 @@ func Decode(s string) ([]byte, error) {
return buf, nil return buf, nil
} }
// Base58Encode encodes a byte slice to be a base58 encoded string. // Encode encodes a byte slice to be a base58 encoded string.
func Encode(bytes []byte) string { func Encode(bytes []byte) string {
var ( var (
lookupTable = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" lookupTable = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
@ -77,47 +80,47 @@ func Encode(bytes []byte) string {
return encoded return encoded
} }
// Base58CheckDecode decodes the given string. // CheckDecode decodes the given string.
// func CheckDecode(s string) (b []byte, err error) { func CheckDecode(s string) (b []byte, err error) {
// b, err = Decode(s) b, err = Decode(s)
// if err != nil { if err != nil {
// return nil, err return nil, err
// } }
// for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
// if s[i] != '1' { if s[i] != '1' {
// break break
// } }
// b = append([]byte{0x00}, b...) b = append([]byte{0x00}, b...)
// } }
// if len(b) < 5 { if len(b) < 5 {
// return nil, fmt.Errorf("Invalid base-58 check string: missing checksum. -1") return nil, fmt.Errorf("Invalid base-58 check string: missing checksum. -1")
// } }
// hash, err := hash.DoubleSha256(b[:len(b)-4]) hash, err := hash.DoubleSha256(b[:len(b)-4])
// if err != nil { if err != nil {
// return nil, fmt.Errorf("Could not double sha256 data") return nil, fmt.Errorf("Could not double sha256 data")
// } }
// if bytes.Compare(hash[0:4], b[len(b)-4:]) != 0 { if bytes.Compare(hash[0:4], b[len(b)-4:]) != 0 {
// return nil, fmt.Errorf("Invalid base-58 check string: invalid checksum. -2") return nil, fmt.Errorf("Invalid base-58 check string: invalid checksum. -2")
// } }
// // Strip the 4 byte long hash. // Strip the 4 byte long hash.
// b = b[:len(b)-4] b = b[:len(b)-4]
// return b, nil return b, nil
// } }
// // Base58checkEncode encodes b into a base-58 check encoded string. // CheckEncode encodes b into a base-58 check encoded string.
// func CheckEncode(b []byte) (string, error) { func CheckEncode(b []byte) (string, error) {
// hash, err := hash.DoubleSha256(b) hash, err := hash.DoubleSha256(b)
// if err != nil { if err != nil {
// return "", fmt.Errorf("Could not double sha256 data") return "", fmt.Errorf("Could not double sha256 data")
// } }
// b = append(b, hash[0:4]...) b = append(b, hash[0:4]...)
// return Encode(b), nil return Encode(b), nil
// } }

View file

@ -8,6 +8,7 @@ import (
"golang.org/x/crypto/ripemd160" "golang.org/x/crypto/ripemd160"
) )
// Sha256 hashes the byte slice using sha256
func Sha256(data []byte) (util.Uint256, error) { func Sha256(data []byte) (util.Uint256, error) {
var hash util.Uint256 var hash util.Uint256
hasher := sha256.New() hasher := sha256.New()
@ -21,6 +22,7 @@ func Sha256(data []byte) (util.Uint256, error) {
return hash, nil return hash, nil
} }
// DoubleSha256 hashes the underlying data twice using sha256
func DoubleSha256(data []byte) (util.Uint256, error) { func DoubleSha256(data []byte) (util.Uint256, error) {
var hash util.Uint256 var hash util.Uint256
@ -36,6 +38,7 @@ func DoubleSha256(data []byte) (util.Uint256, error) {
return hash, nil return hash, nil
} }
// RipeMD160 hashes the underlying data using ripemd160
func RipeMD160(data []byte) (util.Uint160, error) { func RipeMD160(data []byte) (util.Uint160, error) {
var hash util.Uint160 var hash util.Uint160
hasher := ripemd160.New() hasher := ripemd160.New()
@ -49,6 +52,7 @@ func RipeMD160(data []byte) (util.Uint160, error) {
return hash, nil return hash, nil
} }
//Hash160 hashes the underlying data using sha256 then ripemd160
func Hash160(data []byte) (util.Uint160, error) { func Hash160(data []byte) (util.Uint160, error) {
var hash util.Uint160 var hash util.Uint160
h1, err := Sha256(data) h1, err := Sha256(data)
@ -63,6 +67,7 @@ func Hash160(data []byte) (util.Uint160, error) {
return hash, nil return hash, nil
} }
// Checksum calculates the checksum of the byte slice using sha256
func Checksum(data []byte) ([]byte, error) { func Checksum(data []byte) ([]byte, error) {
hash, err := Sum(data) hash, err := Sum(data)
if err != nil { if err != nil {
@ -71,6 +76,7 @@ func Checksum(data []byte) ([]byte, error) {
return hash[:4], nil return hash[:4], nil
} }
// Sum calculates the Sum of the data by using double sha256
func Sum(b []byte) (util.Uint256, error) { func Sum(b []byte) (util.Uint256, error) {
hash, err := DoubleSha256((b)) hash, err := DoubleSha256((b))
return hash, err return hash, err

View file

@ -25,12 +25,16 @@ func (f Fixed8) String() string {
func (f Fixed8) Value() float64 { func (f Fixed8) Value() float64 {
return float64(f) / float64(decimals) return float64(f) / float64(decimals)
} }
// Add adds two Fixed8 values together
func (f Fixed8) Add(val Fixed8) Fixed8 { func (f Fixed8) Add(val Fixed8) Fixed8 {
a := int64(f.Value()) a := int64(f.Value())
b := int64(val.Value()) b := int64(val.Value())
c := a + b c := a + b
return FromInt(c) return FromInt(c)
} }
//Sub subtracts two fixed values from each other
func (f Fixed8) Sub(val Fixed8) Fixed8 { func (f Fixed8) Sub(val Fixed8) Fixed8 {
a := int64(f.Value()) a := int64(f.Value())
b := int64(val.Value()) b := int64(val.Value())
@ -38,18 +42,21 @@ func (f Fixed8) Sub(val Fixed8) Fixed8 {
return FromInt(c) return FromInt(c)
} }
//FromInt returns a Fixed8 objects from an int64
func FromInt(val int64) Fixed8 { func FromInt(val int64) Fixed8 {
return Fixed8(val * decimals) return Fixed8(val * decimals)
} }
// FromFloat returns a Fixed8 object from a float64
func FromFloat(val float64) Fixed8 { func FromFloat(val float64) Fixed8 {
return Fixed8(val * decimals) return Fixed8(val * decimals)
} }
// FromString returns a Fixed8 object from a string
func FromString(val string) (Fixed8, error) { func FromString(val string) (Fixed8, error) {
res, err := strconv.ParseFloat(val, 64) res, err := strconv.ParseFloat(val, 64)
if err != nil { if err != nil {
return 0, fmt.Errorf("Failed at parsing string %s", val) return 0, fmt.Errorf("failed at parsing string %s", val)
} }
return FromFloat(res), nil return FromFloat(res), nil
} }

View file

@ -4,6 +4,7 @@ import (
"os" "os"
) )
// UpdateFile appends a byte slice to a file
func UpdateFile(filename string, data []byte) error { func UpdateFile(filename string, data []byte) error {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)

View file

@ -5,6 +5,7 @@ import (
"net" "net"
) )
//GetLocalIP returns the ip address of the current node
// https://stackoverflow.com/a/37382208 // https://stackoverflow.com/a/37382208
func GetLocalIP() net.IP { func GetLocalIP() net.IP {
conn, err := net.Dial("udp", "8.8.8.8:80") conn, err := net.Dial("udp", "8.8.8.8:80")

View file

@ -1,6 +1,6 @@
package slice package slice
// SliceReverse return a reversed version of the given byte slice. // Reverse return a reversed version of the given byte slice.
func Reverse(b []byte) []byte { func Reverse(b []byte) []byte {
// Protect from big.Ints that have 1 len bytes. // Protect from big.Ints that have 1 len bytes.
if len(b) < 2 { if len(b) < 2 {

View file

@ -44,9 +44,11 @@ func (u Uint256) Bytes() []byte {
} }
return b return b
} }
func (u Uint256) Reverse() (res Uint256) {
res, _ = Uint256DecodeBytes(u.BytesReverse()) // Reverse reverses the Uint256 object
return func (u Uint256) Reverse() Uint256 {
res, _ := Uint256DecodeBytes(u.BytesReverse())
return res
} }
// BytesReverse return a reversed byte representation of u. // BytesReverse return a reversed byte representation of u.

View file

@ -8,18 +8,23 @@ import (
"io/ioutil" "io/ioutil"
) )
// Functions // Convenience function
// BufferLength returns the length of a buffer as uint32
func BufferLength(buf *bytes.Buffer) uint32 { func BufferLength(buf *bytes.Buffer) uint32 {
return uint32(buf.Len()) return uint32(buf.Len())
} }
// SumSHA256 returns the sha256 sum of the data
func SumSHA256(b []byte) []byte { func SumSHA256(b []byte) []byte {
h := sha256.New() h := sha256.New()
h.Write(b) h.Write(b)
return h.Sum(nil) return h.Sum(nil)
} }
// CalculateHash takes a function with a binary writer and returns
// the double hash of the io.Writer
func CalculateHash(f func(bw *BinWriter)) (Uint256, error) { func CalculateHash(f func(bw *BinWriter)) (Uint256, error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
bw := &BinWriter{W: buf} bw := &BinWriter{W: buf}
@ -33,15 +38,12 @@ func CalculateHash(f func(bw *BinWriter)) (Uint256, error) {
} }
func ReaderToBuffer(r io.Reader) (buf *bytes.Buffer, err error) { //ReaderToBuffer converts a io.Reader into a bytes.Buffer
func ReaderToBuffer(r io.Reader) (*bytes.Buffer, error) {
byt, err := ioutil.ReadAll(r) byt, err := ioutil.ReadAll(r)
if err != nil { if err != nil {
return nil, err
return
} }
buf := bytes.NewBuffer(byt)
buf = bytes.NewBuffer(byt) return buf, nil
return
} }