Merge pull request #330 from nspcc-dev/drop-redundant-dev-code-part-5

Drop redundant dev code part 5. The next one in series of #315, #318, #322 and #328. Continuing with #307. Fixes #319 along the way.
This commit is contained in:
Roman Khimov 2019-08-30 20:08:09 +03:00 committed by GitHub
commit c96be81229
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 194 additions and 1819 deletions

View file

@ -1,62 +0,0 @@
# Package - Wire
The neo wire package will implement the network protocol displayed here: http://docs.neo.org/en-us/network/network-protocol.html
This package will act as a standalone package.
# Responsibility
This package will solely be responsible for Encoding and decoding a Message.
It will return a Messager interface, which means that the caller of the package will need to type assert it to the appropriate type.
# Usage
## Write Message
expectedIP := "127.0.0.1"
expectedPort := 8333
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP(expectedIP), Port: expectedPort}
message, err := NewVersionMessage(tcpAddrMe, 0, true, defaultVersion)
conn := new(bytes.Buffer)
if err := WriteMessage(con, Production, message); err != nil {
// handle Error
}
## Read Message
readmsg, err := ReadMessage(conn, Production)
if err != nil {
// Log error
}
version := readmsg.(*VersionMessage)
## RoadMap
These below commands are left to implement.
[ x ] CMDVersion (Tests added)
[ x ] CMDVerack (Tests Added)
[ x ] CMDGetAddr(Tests Added)
[ x ] CMDAddr (Tests Added)
[ x ] CMDGetHeaders (Tests Added)
[ x ] CMDHeaders (Tests Added)
[ x ] CMDGetBlocks (Tests Added)
[ x ] CMDInv (Tests Added)
[ x ] CMDGetData (Tests Added)
[ x ] CMDBlock (Tests Added)
[ x ] CMDTX // Each tx implments the messager interface
[ ] CMDConsensus
## Notes
Please not that this package will do sanity checks on the fields, however it will not verify if any of the items are valid for the current state of the system. Please see `Responbilities`.
The difference between Encode/Decode and EncodePayload/DecodePayload, is the parameter type.
In most cases, Encode/Decode is just a convenience method.
# Contributors
When modifying this package, please ensure that it does not depend on any other package and that it conforms to the Single Responsibility Principle. If you see somewhere in the current implementation that does not do this, then please tell me.

View file

@ -1,42 +0,0 @@
package wire
import (
"io"
"github.com/CityOfZion/neo-go/pkg/wire/command"
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
// Base is everything in the message except the payload
type Base struct {
Magic uint32
CMD command.Type
PayloadLength uint32
Checksum uint32
}
// DecodeBase will decode an io.Reader into a Base object
// Note, That there is no EncodeBase, As the header is implicitly inferred from the message on Encode To send
func (h *Base) DecodeBase(r io.Reader) (io.Reader, error) {
br := &util.BinReader{R: r}
br.Read(&h.Magic)
var cmd [12]byte
br.Read(&cmd)
h.CMD = command.Type(cmdByteArrayToString(cmd))
br.Read(&h.PayloadLength)
br.Read(&h.Checksum)
return br.R, br.Err
}
func cmdByteArrayToString(cmd [command.Size]byte) string {
buf := []byte{}
for i := 0; i < command.Size; i++ {
if cmd[i] != 0 {
buf = append(buf, cmd[i])
}
}
return string(buf)
}

View file

@ -1,156 +0,0 @@
package wire
import (
"bufio"
"bytes"
"errors"
"io"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction"
checksum "github.com/CityOfZion/neo-go/pkg/wire/util/Checksum"
"github.com/CityOfZion/neo-go/pkg/wire/command"
"github.com/CityOfZion/neo-go/pkg/wire/payload"
"github.com/CityOfZion/neo-go/pkg/wire/protocol"
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
// Messager is implemented by any object that can
// Encode and Decode Payloads
type Messager interface {
// EncodePayload takes a message payload and encodes it
EncodePayload(w io.Writer) error
// DecodePayload takes an io.Reader and decodes it into
// a message payload
DecodePayload(r io.Reader) error
// Command returns the assosciated command type
Command() command.Type
}
const (
// Magic + cmd + length + checksum
minMsgSize = 4 + 12 + 4 + 4
)
var (
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 {
bw := &util.BinWriter{W: w}
bw.Write(magic)
bw.Write(cmdToByteArray(message.Command()))
buf := new(bytes.Buffer)
if err := message.EncodePayload(buf); err != nil {
return err
}
payloadLen := uint32(buf.Len())
checksum := checksum.FromBytes(buf.Bytes())
bw.Write(payloadLen)
bw.Write(checksum)
bw.WriteBigEnd(buf.Bytes())
return bw.Err
}
// ReadMessage will read a message from a given io.Reader
func ReadMessage(r io.Reader, magic protocol.Magic) (Messager, error) {
byt := make([]byte, minMsgSize)
if _, err := io.ReadFull(r, byt); err != nil {
return nil, err
}
reader := bytes.NewReader(byt)
var header Base
_, err := header.DecodeBase(reader)
if err != nil {
return nil, errors.New("Error decoding into the header base")
}
buf := new(bytes.Buffer)
_, err = io.CopyN(buf, r, int64(header.PayloadLength))
if err != nil {
return nil, err
}
// Compare the checksum of the payload.
if !checksum.Compare(header.Checksum, buf.Bytes()) {
return nil, errChecksumMismatch
}
switch header.CMD {
case command.Version:
v := &payload.VersionMessage{}
err := v.DecodePayload(buf)
return v, err
case command.Verack:
v, err := payload.NewVerackMessage()
err = v.DecodePayload(buf)
return v, err
case command.Inv:
v, err := payload.NewInvMessage(0)
err = v.DecodePayload(buf)
return v, err
case command.GetAddr:
v, err := payload.NewGetAddrMessage()
err = v.DecodePayload(buf)
return v, err
case command.Addr:
v, err := payload.NewAddrMessage()
err = v.DecodePayload(buf)
return v, err
case command.Block:
v, err := payload.NewBlockMessage()
err = v.DecodePayload(buf)
return v, err
case command.GetBlocks:
v, err := payload.NewGetBlocksMessage([]util.Uint256{}, util.Uint256{})
err = v.DecodePayload(buf)
return v, err
case command.GetData:
v, err := payload.NewGetDataMessage(payload.InvTypeTx)
err = v.DecodePayload(buf)
return v, err
case command.GetHeaders:
v, err := payload.NewGetHeadersMessage([]util.Uint256{}, util.Uint256{})
err = v.DecodePayload(buf)
return v, err
case command.Headers:
v, err := payload.NewHeadersMessage()
err = v.DecodePayload(buf)
return v, err
case command.TX:
reader := bufio.NewReader(buf)
tx, err := transaction.FromReader(reader)
if err != nil {
return nil, err
}
return payload.NewTXMessage(tx)
}
return nil, errors.New("Unknown Message found")
}
func cmdToByteArray(cmd command.Type) [command.Size]byte {
cmdLen := len(cmd)
if cmdLen > command.Size {
panic("exceeded command max length of size 12")
}
// The command can have max 12 bytes, rest is filled with 0.
b := [command.Size]byte{}
for i := 0; i < cmdLen; i++ {
b[i] = cmd[i]
}
return b
}

View file

@ -1,55 +0,0 @@
package wire
import (
"bytes"
"net"
"testing"
"github.com/CityOfZion/neo-go/pkg/wire/payload"
"github.com/CityOfZion/neo-go/pkg/wire/protocol"
"github.com/stretchr/testify/assert"
)
// This is quite hard to test because the message uses time.Now()
// TODO: Test each field expect time.Now(), just make sure it is a uint32
func TestWriteMessageLen(t *testing.T) {
expectedIP := "127.0.0.1"
expectedPort := 8333
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP(expectedIP), Port: expectedPort}
message, err := payload.NewVersionMessage(tcpAddrMe, 0, true, protocol.DefaultVersion, protocol.UserAgent, 100, protocol.NodePeerService)
if err != nil {
assert.Fail(t, err.Error())
}
buf := new(bytes.Buffer)
if err := WriteMessage(buf, protocol.MainNet, message); err != nil {
assert.Fail(t, err.Error())
}
assert.Equal(t, 60, len(buf.Bytes()))
}
func TestReadMessage(t *testing.T) {
expectedIP := "127.0.0.1"
expectedPort := 8333
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP(expectedIP), Port: expectedPort}
message, err := payload.NewVersionMessage(tcpAddrMe, 23, true, protocol.DefaultVersion, protocol.UserAgent, 100, protocol.NodePeerService)
if err != nil {
assert.Fail(t, err.Error())
}
buf := new(bytes.Buffer)
if err := WriteMessage(buf, protocol.MainNet, message); err != nil {
assert.Fail(t, err.Error())
}
readmsg, err := ReadMessage(buf, protocol.MainNet)
if err != nil {
assert.Fail(t, err.Error())
}
version := readmsg.(*payload.VersionMessage)
assert.Equal(t, 23, int(version.StartHeight))
// If MessageReading was unsuccessfull it will return a nil object
}

View file

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

View file

@ -1,61 +0,0 @@
package transaction
import (
"errors"
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
// Attribute represents a Transaction attribute.
type Attribute struct {
Usage AttrUsage
Data []byte
}
var errMaxData = errors.New("max Size of Attribute reached")
const maxAttrSize = 65535
// Encode encodes the given Attribute into the binary writer
func (a *Attribute) Encode(bw *util.BinWriter) {
if len(a.Data) > maxAttrSize {
bw.Err = errMaxData
return
}
bw.Write(uint8(a.Usage))
if a.Usage == ContractHash || a.Usage == Vote || (a.Usage >= Hash1 && a.Usage <= Hash15) {
bw.Write(a.Data[:32])
} else if a.Usage == ECDH02 || a.Usage == ECDH03 {
bw.Write(a.Data[1:33])
} else if a.Usage == Script {
bw.Write(a.Data[:20])
} else if a.Usage == DescriptionURL || a.Usage == Description || a.Usage >= Remark {
bw.VarUint(uint64(len(a.Data)))
bw.Write(a.Data)
} else {
bw.Write(a.Data)
}
}
// Decode decodes the binary reader into an Attribute object
func (a *Attribute) Decode(br *util.BinReader) {
br.Read(&a.Usage)
if a.Usage == ContractHash || a.Usage == Vote || a.Usage >= Hash1 && a.Usage <= Hash15 {
a.Data = make([]byte, 32)
br.Read(&a.Data)
} else if a.Usage == ECDH02 || a.Usage == ECDH03 {
a.Data = make([]byte, 32)
br.Read(&a.Data)
} else if a.Usage == Script {
a.Data = make([]byte, 20)
br.Read(&a.Data)
} else if a.Usage == DescriptionURL || a.Usage == Description || a.Usage >= Remark {
lenData := br.VarUint()
a.Data = make([]byte, lenData)
br.Read(&a.Data)
} else {
br.Read(&a.Data)
}
}

View file

@ -1,32 +0,0 @@
package transaction
import "github.com/CityOfZion/neo-go/pkg/wire/util"
// Input represents a Transaction input.
type Input struct {
// The hash of the previous transaction.
PrevHash util.Uint256
// The index of the previous transaction.
PrevIndex uint16
}
//NewInput returns a transaction input object
func NewInput(prevHash util.Uint256, prevIndex uint16) *Input {
return &Input{
prevHash,
prevIndex,
}
}
// Encode encodes the given input into a binary writer
func (i *Input) Encode(bw *util.BinWriter) {
bw.Write(i.PrevHash)
bw.Write(i.PrevIndex)
}
// Decode decodes a binary reader into an input object
func (i *Input) Decode(br *util.BinReader) {
br.Read(&i.PrevHash)
br.Read(&i.PrevIndex)
}

View file

@ -1,38 +0,0 @@
package transaction
import "github.com/CityOfZion/neo-go/pkg/wire/util"
// Output represents a transaction output in the neo-network
type Output struct {
// The NEO asset id used in the transaction.
AssetID util.Uint256
// Amount of AssetType send or received.
Amount int64
// The address of the remittee.
ScriptHash util.Uint160
}
//NewOutput returns an output object
func NewOutput(assetID util.Uint256, Amount int64, ScriptHash util.Uint160) *Output {
return &Output{
assetID,
Amount,
ScriptHash,
}
}
// Encode encodes the Output into a binary writer
func (o *Output) Encode(bw *util.BinWriter) {
bw.Write(o.AssetID)
bw.Write(o.Amount)
bw.Write(o.ScriptHash)
}
// Decode decodes a binary reader into an output object
func (o *Output) Decode(br *util.BinReader) {
br.Read(&o.AssetID)
br.Read(&o.Amount)
br.Read(&o.ScriptHash)
}

View file

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

View file

@ -1,16 +0,0 @@
package transaction
// AssetType represent a NEO asset type
type AssetType uint8
// Valid asset types.
const (
CreditFlag AssetType = 0x40
DutyFlag AssetType = 0x80
GoverningToken AssetType = 0x00
UtilityToken AssetType = 0x01
Currency AssetType = 0x08
Share AssetType = DutyFlag | 0x10
Invoice AssetType = DutyFlag | 0x18
Token AssetType = CreditFlag | 0x20
)

View file

@ -1,49 +0,0 @@
package transaction
// AttrUsage represents an attribute usage on the neo network
type AttrUsage uint8
// List of valid attribute usages.
const (
ContractHash AttrUsage = 0x00
ECDH02 AttrUsage = 0x02
ECDH03 AttrUsage = 0x03
Script AttrUsage = 0x20
Vote AttrUsage = 0x30
CertURL AttrUsage = 0x80
DescriptionURL AttrUsage = 0x81
Description AttrUsage = 0x90
Hash1 AttrUsage = 0xa1
Hash2 AttrUsage = 0xa2
Hash3 AttrUsage = 0xa3
Hash4 AttrUsage = 0xa4
Hash5 AttrUsage = 0xa5
Hash6 AttrUsage = 0xa6
Hash7 AttrUsage = 0xa7
Hash8 AttrUsage = 0xa8
Hash9 AttrUsage = 0xa9
Hash10 AttrUsage = 0xaa
Hash11 AttrUsage = 0xab
Hash12 AttrUsage = 0xac
Hash13 AttrUsage = 0xad
Hash14 AttrUsage = 0xae
Hash15 AttrUsage = 0xaf
Remark AttrUsage = 0xf0
Remark1 AttrUsage = 0xf1
Remark2 AttrUsage = 0xf2
Remark3 AttrUsage = 0xf3
Remark4 AttrUsage = 0xf4
Remark5 AttrUsage = 0xf5
Remark6 AttrUsage = 0xf6
Remark7 AttrUsage = 0xf7
Remark8 AttrUsage = 0xf8
Remark9 AttrUsage = 0xf9
Remark10 AttrUsage = 0xfa
Remark11 AttrUsage = 0xfb
Remark12 AttrUsage = 0xfc
Remark13 AttrUsage = 0xfd
Remark14 AttrUsage = 0xfe
Remark15 AttrUsage = 0xff
)

View file

@ -1,202 +0,0 @@
package transaction
import (
"bytes"
"io"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/version"
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
type encodeExclusiveFields func(bw *util.BinWriter)
type decodeExclusiveFields func(br *util.BinReader)
// Transactioner is the interface that will unite the
// transaction types. Each transaction will implement this interface
// and so wil be a transactioner
type Transactioner interface {
Encode(w io.Writer) error
Decode(r io.Reader) error
BaseTx() *Base
ID() (util.Uint256, error)
}
// Base transaction is the template for all other transactions
// It contains all of the shared fields between transactions and
// the additional encodeExclusive and decodeExclusive methods, which
// can be overwitten in the other transactions to encode the non shared fields
type Base struct {
Type types.TX
Version version.TX
Inputs []*Input
Outputs []*Output
Attributes []*Attribute
Witnesses []*Witness
Hash util.Uint256
encodeExclusive encodeExclusiveFields
decodeExclusive decodeExclusiveFields
}
func createBaseTransaction(typ types.TX, ver version.TX) *Base {
return &Base{
Type: typ,
Version: ver,
Inputs: []*Input{},
Outputs: []*Output{},
Attributes: []*Attribute{},
Witnesses: []*Witness{},
}
}
// Decode implements the transactioner interface
func (b *Base) Decode(r io.Reader) error {
br := &util.BinReader{R: r}
return b.DecodePayload(br)
}
// Encode implements the transactioner interface
func (b *Base) Encode(w io.Writer) error {
bw := &util.BinWriter{W: w}
b.EncodePayload(bw)
return bw.Err
}
//EncodePayload implements the Messager interface
func (b *Base) EncodePayload(bw *util.BinWriter) {
b.encodeHashableFields(bw)
lenWitnesses := uint64(len(b.Witnesses))
bw.VarUint(lenWitnesses)
for _, witness := range b.Witnesses {
witness.Encode(bw)
}
}
// DecodePayload implements the messager interface
func (b *Base) DecodePayload(br *util.BinReader) error {
b.decodeHashableFields(br)
lenWitnesses := br.VarUint()
b.Witnesses = make([]*Witness, lenWitnesses)
for i := 0; i < int(lenWitnesses); i++ {
b.Witnesses[i] = &Witness{}
b.Witnesses[i].Decode(br)
}
if br.Err != nil {
return br.Err
}
return b.createHash()
}
func (b *Base) encodeHashableFields(bw *util.BinWriter) {
b.Type.Encode(bw)
b.Version.Encode(bw)
b.encodeExclusive(bw)
lenAttrs := uint64(len(b.Attributes))
lenInputs := uint64(len(b.Inputs))
lenOutputs := uint64(len(b.Outputs))
bw.VarUint(lenAttrs)
for _, attr := range b.Attributes {
attr.Encode(bw)
}
bw.VarUint(lenInputs)
for _, input := range b.Inputs {
input.Encode(bw)
}
bw.VarUint(lenOutputs)
for _, output := range b.Outputs {
output.Encode(bw)
}
}
func (b *Base) decodeHashableFields(br *util.BinReader) {
b.Type.Decode(br)
b.Version.Decode(br)
b.decodeExclusive(br)
lenAttrs := br.VarUint()
b.Attributes = make([]*Attribute, lenAttrs)
for i := 0; i < int(lenAttrs); i++ {
b.Attributes[i] = &Attribute{}
b.Attributes[i].Decode(br)
}
lenInputs := br.VarUint()
b.Inputs = make([]*Input, lenInputs)
for i := 0; i < int(lenInputs); i++ {
b.Inputs[i] = &Input{}
b.Inputs[i].Decode(br)
}
lenOutputs := br.VarUint()
b.Outputs = make([]*Output, lenOutputs)
for i := 0; i < int(lenOutputs); i++ {
b.Outputs[i] = &Output{}
b.Outputs[i].Decode(br)
}
}
// AddInput adds an input to the transaction
func (b *Base) AddInput(i *Input) {
b.Inputs = append(b.Inputs, i)
}
// AddOutput adds an output to the transaction
func (b *Base) AddOutput(o *Output) {
b.Outputs = append(b.Outputs, o)
}
// AddAttribute adds an attribute to the transaction
func (b *Base) AddAttribute(a *Attribute) {
b.Attributes = append(b.Attributes, a)
}
// AddWitness adds a witness object to the transaction
func (b *Base) AddWitness(w *Witness) {
b.Witnesses = append(b.Witnesses, w)
}
func (b *Base) createHash() error {
hash, err := util.CalculateHash(b.encodeHashableFields)
b.Hash = hash
return err
}
// ID returns the TXID of the transaction
func (b *Base) ID() (util.Uint256, error) {
var emptyHash util.Uint256
var err error
if b.Hash == emptyHash {
err = b.createHash()
}
return b.Hash, err
}
// Bytes returns the raw bytes of the tx
func (b *Base) Bytes() []byte {
buf := new(bytes.Buffer)
b.Encode(buf)
return buf.Bytes()
}
// BaseTx returns the Base object in a transaction
func (b *Base) BaseTx() *Base {
return b
}

View file

@ -1,43 +0,0 @@
package transaction
import (
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/version"
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
//Claim represents a claim transaction on the neo network
type Claim struct {
*Base
Claims []*Input
}
//NewClaim returns a ClaimTransaction
func NewClaim(ver version.TX) *Claim {
basicTrans := createBaseTransaction(types.Contract, ver)
claim := &Claim{}
claim.Base = basicTrans
claim.encodeExclusive = claim.encodeExcl
claim.decodeExclusive = claim.decodeExcl
return claim
}
func (c *Claim) encodeExcl(bw *util.BinWriter) {
bw.VarUint(uint64(len(c.Claims)))
for _, claim := range c.Claims {
claim.Encode(bw)
}
}
func (c *Claim) decodeExcl(br *util.BinReader) {
lenClaims := br.VarUint()
c.Claims = make([]*Input, lenClaims)
for i := 0; i < int(lenClaims); i++ {
c.Claims[i] = &Input{}
c.Claims[i].Decode(br)
}
}

View file

@ -1,38 +0,0 @@
package transaction
import (
"bytes"
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeClaim(t *testing.T) {
// test taken from mainnet: abf142faf539c340e42722b5b34b505cf4fd73185fed775784e37c2c5ef1b866
rawtx := "020001af1b3a0f3729572893ce4e82f2113d18ec9a5e9d6fe02117eaa9e0c5a43770490000000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6048ae5801000000001123b6b74273562540479eea5cd0139f88ac7dd301414085f6d9edc24ab68c5d15c8e164de6702106c53bc15fa2c45b575bd3543c19132de61dd1922407be56affbcea73e5f8878811549340fd3c951e8593d51f3c8a962321028cf5e5a4d430db0202755c2cf1b3c99efcb4da4e41e182450dc5e1ddffb54bbfac"
rawtxBytes, _ := hex.DecodeString(rawtx)
c := NewClaim(0)
r := bytes.NewReader(rawtxBytes)
err := c.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, types.Claim, c.Type)
assert.Equal(t, 0, int(c.Version))
assert.Equal(t, 1, int(len(c.Claims)))
claim := c.Claims[0]
assert.Equal(t, "497037a4c5e0a9ea1721e06f9d5e9aec183d11f2824ece93285729370f3a1baf", claim.PrevHash.ReverseString())
assert.Equal(t, uint16(0), claim.PrevIndex)
assert.Equal(t, "abf142faf539c340e42722b5b34b505cf4fd73185fed775784e37c2c5ef1b866", c.Hash.ReverseString())
// Encode
buf := new(bytes.Buffer)
err = c.Encode(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}

View file

@ -1,28 +0,0 @@
package transaction
import (
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/version"
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
//Contract represents a contract transaction on the neo network
type Contract struct {
*Base
}
//NewContract returns a contract transaction
func NewContract(ver version.TX) *Contract {
basicTrans := createBaseTransaction(types.Contract, ver)
contract := &Contract{
basicTrans,
}
contract.encodeExclusive = contract.encodeExcl
contract.decodeExclusive = contract.decodeExcl
return contract
}
func (c *Contract) encodeExcl(bw *util.BinWriter) {}
func (c *Contract) decodeExcl(br *util.BinReader) {}

View file

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

View file

@ -1,30 +0,0 @@
package transaction
import (
"bytes"
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeEnrollment(t *testing.T) {
rawtx := "200002ff8ac54687f36bbc31a91b730cc385da8af0b581f2d59d82b5cfef824fd271f60001d3d3b7028d61fea3b7803fda3d7f0a1f7262d38e5e1c8987b0313e0a94574151000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c60005441d11600000050ac4949596f5b62fef7be4d1c3e494e6048ed4a01414079d78189d591097b17657a62240c93595e8233dc81157ea2cd477813f09a11fd72845e6bd97c5a3dda125985ea3d5feca387e9933649a9a671a69ab3f6301df6232102ff8ac54687f36bbc31a91b730cc385da8af0b581f2d59d82b5cfef824fd271f6ac"
rawtxBytes, _ := hex.DecodeString(rawtx)
enroll := NewEnrollment(30)
r := bytes.NewReader(rawtxBytes)
err := enroll.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, types.Enrollment, enroll.Type)
buf := new(bytes.Buffer)
err = enroll.Encode(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
assert.Equal(t, "988832f693785dcbcb8d5a0e9d5d22002adcbfb1eb6bbeebf8c494fff580e147", enroll.Hash.ReverseString())
}

View file

@ -1,61 +0,0 @@
package transaction
import (
"errors"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/version"
"github.com/CityOfZion/neo-go/pkg/wire/util"
"github.com/CityOfZion/neo-go/pkg/wire/util/fixed8"
)
//Invocation represents an invocation transaction on the neo network
type Invocation struct {
*Base
Script []byte
Gas fixed8.Fixed8
}
//NewInvocation returns an invocation transaction
func NewInvocation(ver version.TX) *Invocation {
basicTrans := createBaseTransaction(types.Invocation, ver)
invocation := &Invocation{}
invocation.Base = basicTrans
invocation.encodeExclusive = invocation.encodeExcl
invocation.decodeExclusive = invocation.decodeExcl
return invocation
}
func (c *Invocation) encodeExcl(bw *util.BinWriter) {
bw.VarUint(uint64(len(c.Script)))
bw.Write(c.Script)
switch c.Version {
case 0:
c.Gas = fixed8.Fixed8(0)
case 1:
bw.Write(&c.Gas)
default:
bw.Write(&c.Gas)
}
return
}
func (c *Invocation) decodeExcl(br *util.BinReader) {
lenScript := br.VarUint()
c.Script = make([]byte, lenScript)
br.Read(&c.Script)
switch c.Version {
case 0:
c.Gas = fixed8.Fixed8(0)
case 1:
br.Read(&c.Gas)
default:
br.Err = errors.New("invalid Version Number for Invocation Transaction")
}
return
}

View file

@ -1,78 +0,0 @@
package transaction
import (
"bytes"
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeInvoc(t *testing.T) {
// taken from mainnet b2a22cd9dd7636ae23e25576866cd1d9e2f3d85a85e80874441f085cd60006d1
rawtx := "d10151050034e23004141ad842821c7341d5a32b17d7177a1750d30014ca14628c9e5bc6a9346ca6bcdf050ceabdeb2bdc774953c1087472616e736665726703e1df72015bdef1a1b9567d4700635f23b1f406f100000000000000000220628c9e5bc6a9346ca6bcdf050ceabdeb2bdc7749f02f31363a30373a3032203a2030333366616431392d643638322d343035382d626437662d31356339333132343433653800000141403ced56c16f933e0a0a7d37470e114f6a4216ef9b834d61db67b74b9bd117370d10870857c0ee8adcf9956bc9fc92c5158de0c2db34ef459c17de042f20ad8fe92321027392870a5994b090d1750dda173a54df8dad324ed6d9ed25290d17c59059a112ac"
rawtxBytes, _ := hex.DecodeString(rawtx)
i := NewInvocation(30)
r := bytes.NewReader(rawtxBytes)
err := i.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, types.Invocation, i.Type)
assert.Equal(t, 2, len(i.Attributes))
attr1 := i.Attributes[0]
assert.Equal(t, Script, attr1.Usage)
assert.Equal(t, "628c9e5bc6a9346ca6bcdf050ceabdeb2bdc7749", hex.EncodeToString(attr1.Data))
attr2 := i.Attributes[1]
assert.Equal(t, Remark, attr2.Usage)
assert.Equal(t, "31363a30373a3032203a2030333366616431392d643638322d343035382d626437662d313563393331323434336538", hex.EncodeToString(attr2.Data))
assert.Equal(t, "050034e23004141ad842821c7341d5a32b17d7177a1750d30014ca14628c9e5bc6a9346ca6bcdf050ceabdeb2bdc774953c1087472616e736665726703e1df72015bdef1a1b9567d4700635f23b1f406f1", hex.EncodeToString(i.Script))
assert.Equal(t, "b2a22cd9dd7636ae23e25576866cd1d9e2f3d85a85e80874441f085cd60006d1", i.Hash.ReverseString())
// Encode
buf := new(bytes.Buffer)
err = i.Encode(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtxBytes, buf.Bytes())
}
func TestEncodeDecodeInvocAttributes(t *testing.T) {
// taken from mainnet cb0b5edc7e87b3b1bd9e029112fd3ce17c16d3de20c43ca1c0c26f3add578ecb
rawtx := "d1015308005b950f5e010000140000000000000000000000000000000000000000141a1e29d6232d2148e1e71e30249835ea41eb7a3d53c1087472616e7366657267fb1c540417067c270dee32f21023aa8b9b71abce000000000000000002201a1e29d6232d2148e1e71e30249835ea41eb7a3d8110f9f504da6334935a2db42b18296d88700000014140461370f6847c4abbdddff54a3e1337e453ecc8133c882ec5b9aabcf0f47dafd3432d47e449f4efc77447ef03519b7808c450a998cca3ecc10e6536ed9db862ba23210285264b6f349f0fe86e9bb3044fde8f705b016593cf88cd5e8a802b78c7d2c950ac"
rawtxBytes, _ := hex.DecodeString(rawtx)
i := NewInvocation(30)
r := bytes.NewReader(rawtxBytes)
err := i.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, types.Invocation, i.Type)
assert.Equal(t, 1, int(i.Version))
assert.Equal(t, 2, len(i.Attributes))
assert.Equal(t, Script, i.Attributes[0].Usage)
assert.Equal(t, "1a1e29d6232d2148e1e71e30249835ea41eb7a3d", hex.EncodeToString(i.Attributes[0].Data))
assert.Equal(t, DescriptionURL, i.Attributes[1].Usage)
assert.Equal(t, "f9f504da6334935a2db42b18296d8870", hex.EncodeToString(i.Attributes[1].Data))
assert.Equal(t, "08005b950f5e010000140000000000000000000000000000000000000000141a1e29d6232d2148e1e71e30249835ea41eb7a3d53c1087472616e7366657267fb1c540417067c270dee32f21023aa8b9b71abce", hex.EncodeToString(i.Script))
assert.Equal(t, "cb0b5edc7e87b3b1bd9e029112fd3ce17c16d3de20c43ca1c0c26f3add578ecb", i.Hash.ReverseString())
// Encode
buf := new(bytes.Buffer)
err = i.Encode(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtxBytes, buf.Bytes())
}

View file

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

View file

@ -1,8 +0,0 @@
package transaction
import "testing"
func TestEncodeDecodeIssue(t *testing.T) {
// This is the same as Contract, as it has no special fields.
}

View file

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

View file

@ -1,17 +0,0 @@
package transaction
// ParamType represent the Type of the contract parameter
type ParamType uint8
// A list of supported smart contract parameter types.
const (
SignatureType ParamType = iota
BoolType
IntegerType
Hash160Type
Hash256Type
ByteArrayType
PublicKeyType
StringType
ArrayType
)

View file

@ -1,38 +0,0 @@
package transaction
import (
"errors"
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
// PublicKey represents a public key on the neo network
type PublicKey struct {
Key []byte
}
//Encode encodes a public key into a binary writer
func (p *PublicKey) Encode(bw *util.BinWriter) {
bw.Write(p.Key)
}
// Decode decodes a bianry reader into a public key
func (p *PublicKey) Decode(br *util.BinReader) {
var prefix uint8
br.Read(&prefix)
// Compressed public keys.
if prefix == 0x02 || prefix == 0x03 {
p.Key = make([]byte, 32)
br.Read(p.Key)
} else if prefix == 0x04 {
p.Key = make([]byte, 65)
br.Read(p.Key)
} else if prefix == 0x00 {
// do nothing, For infinity, the p.Key == 0x00, included in the prefix
} else {
br.Err = errors.New("Prefix not recognised for public key")
return
}
p.Key = append([]byte{prefix}, p.Key...)
}

View file

@ -1,90 +0,0 @@
package transaction
import (
"errors"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/version"
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
// Publish represents a publish transaction on the neo network
type Publish struct {
*Base
Script []byte
ParamList []ParamType
ReturnType ParamType
NeedStorage byte
Name string
CodeVersion string
Author string
Email string
Description string
}
//NewPublish returns a publish transaction
func NewPublish(ver version.TX) *Publish {
basicTrans := createBaseTransaction(types.Publish, ver)
Publish := &Publish{}
Publish.Base = basicTrans
Publish.encodeExclusive = Publish.encodeExcl
Publish.decodeExclusive = Publish.decodeExcl
return Publish
}
func (p *Publish) encodeExcl(bw *util.BinWriter) {
bw.VarBytes(p.Script)
bw.VarUint(uint64(len(p.ParamList)))
for _, param := range p.ParamList {
bw.Write(param)
}
bw.Write(p.ReturnType)
switch p.Version {
case 0:
p.NeedStorage = byte(0)
case 1:
bw.Write(p.NeedStorage)
default:
bw.Err = errors.New("Version Number unknown for Publish Transaction")
}
bw.VarString(p.Name)
bw.VarString(p.CodeVersion)
bw.VarString(p.Author)
bw.VarString(p.Email)
bw.VarString(p.Description)
}
func (p *Publish) decodeExcl(br *util.BinReader) {
p.Script = br.VarBytes()
lenParams := br.VarUint()
p.ParamList = make([]ParamType, lenParams)
for i := 0; i < int(lenParams); i++ {
var ptype uint8
br.Read(&ptype)
p.ParamList[i] = ParamType(ptype)
}
var rtype uint8
br.Read(&rtype)
p.ReturnType = ParamType(rtype)
switch p.Version {
case 0:
p.NeedStorage = byte(0)
case 1:
br.Read(&p.NeedStorage)
default:
br.Err = errors.New("Version Number unknown for Publish Transaction")
}
p.Name = br.VarString()
p.CodeVersion = br.VarString()
p.Author = br.VarString()
p.Email = br.VarString()
p.Description = br.VarString()
}

View file

@ -1,33 +0,0 @@
package transaction
import (
"bytes"
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodePublish(t *testing.T) {
///transaction taken from neo-python; can be found on testnet 5467a1fc8723ceffa8e5ee59399b02eea1df6fbaa53768c6704b90b960d223fa
// taken from neo-python;
rawtx := "d000fd3f01746b4c04000000004c04000000004c040000000061681e416e745368617265732e426c6f636b636861696e2e476574486569676874681d416e745368617265732e426c6f636b636861696e2e476574426c6f636b744c0400000000948c6c766b947275744c0402000000936c766b9479744c0400000000948c6c766b9479681d416e745368617265732e4865616465722e47657454696d657374616d70a0744c0401000000948c6c766b947275744c0401000000948c6c766b9479641b004c0400000000744c0402000000948c6c766b947275623000744c0401000000936c766b9479744c0400000000936c766b9479ac744c0402000000948c6c766b947275620300744c0402000000948c6c766b947961748c6c766b946d748c6c766b946d748c6c766b946d746c768c6b946d746c768c6b946d746c768c6b946d6c75660302050001044c6f636b0c312e302d70726576696577310a4572696b205a68616e67126572696b40616e747368617265732e6f7267234c6f636b20796f75722061737365747320756e74696c20612074696d657374616d702e00014e23ac4c4851f93407d4c59e1673171f39859db9e7cac72540cd3cc1ae0cca87000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6000ebcaaa0d00000067f97110a66136d38badc7b9f88eab013027ce49014140c298da9f06d5687a0bb87ea3bba188b7dcc91b9667ea5cb71f6fdefe388f42611df29be9b2d6288655b9f2188f46796886afc3b37d8b817599365d9e161ecfb62321034b44ed9c8a88fb2497b6b57206cc08edd42c5614bd1fee790e5b795dee0f4e11ac"
rawtxBytes, _ := hex.DecodeString(rawtx)
publ := NewPublish(30)
r := bytes.NewReader(rawtxBytes)
err := publ.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, types.Publish, publ.Type)
buf := new(bytes.Buffer)
err = publ.Encode(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
assert.Equal(t, "5467a1fc8723ceffa8e5ee59399b02eea1df6fbaa53768c6704b90b960d223fa", publ.Hash.ReverseString())
}

View file

@ -1,58 +0,0 @@
package transaction
import (
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/version"
"github.com/CityOfZion/neo-go/pkg/wire/util"
"github.com/CityOfZion/neo-go/pkg/wire/util/fixed8"
)
// Register represents a register transaction on the neo network
type Register struct {
*Base
// The type of the asset being registered.
AssetType AssetType
// Name of the asset being registered.
Name string
// Amount registered
// Unlimited mode -0.00000001
Amount fixed8.Fixed8
// Decimals
Precision uint8
// Public key of the owner
Owner PublicKey
Admin util.Uint160
}
//NewRegister returns a register transaction
func NewRegister(ver version.TX) *Register {
basicTrans := createBaseTransaction(types.Register, ver)
Register := &Register{}
Register.Base = basicTrans
Register.encodeExclusive = Register.encodeExcl
Register.decodeExclusive = Register.decodeExcl
return Register
}
func (r *Register) encodeExcl(bw *util.BinWriter) {
bw.Write(r.AssetType)
bw.VarString(r.Name)
bw.Write(r.Amount)
bw.Write(r.Precision)
r.Owner.Encode(bw)
bw.Write(r.Admin)
}
func (r *Register) decodeExcl(br *util.BinReader) {
br.Read(&r.AssetType)
r.Name = br.VarString()
br.Read(&r.Amount)
br.Read(&r.Precision)
r.Owner.Decode(br)
br.Read(&r.Admin)
}

View file

@ -1,54 +0,0 @@
package transaction
import (
"bytes"
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeRegister(t *testing.T) {
// transaction taken from neo-python; can be found on testnet 0c092117b4ba47b81001712425e6e7f760a637695eaf23741ba335925b195ecd
rawtx := "400060245b7b226c616e67223a227a682d434e222c226e616d65223a2254657374436f696e227d5dffffffffffffffff08034b44ed9c8a88fb2497b6b57206cc08edd42c5614bd1fee790e5b795dee0f4e1167f97110a66136d38badc7b9f88eab013027ce4900014423a26aeca49cdeeb9522c720e1ae3a93bbe27d53662839b16a438305c20906010001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c60001e1a210b00000067f97110a66136d38badc7b9f88eab013027ce490141405d8223ec807e3416a220a75ef9805dfa2e36bd4f6dcc7372373aa45f15c7fadfc96a8642e52acf56c2c66d549be4ba820484873d5cada00b9c1ce9674fbf96382321034b44ed9c8a88fb2497b6b57206cc08edd42c5614bd1fee790e5b795dee0f4e11ac"
rawtxBytes, _ := hex.DecodeString(rawtx)
reg := NewRegister(0)
r := bytes.NewReader(rawtxBytes)
err := reg.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, types.Register, reg.Type)
buf := new(bytes.Buffer)
err = reg.Encode(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
assert.Equal(t, "0c092117b4ba47b81001712425e6e7f760a637695eaf23741ba335925b195ecd", reg.Hash.ReverseString())
}
func TestEncodeDecodeGenesisRegister(t *testing.T) {
// genesis transaction taken from mainnet; can be found on mainnet(Block 0) : c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b
rawtx := "400000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b00000000"
rawtxBytes, _ := hex.DecodeString(rawtx)
reg := NewRegister(0)
r := bytes.NewReader(rawtxBytes)
err := reg.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, types.Register, reg.Type)
buf := new(bytes.Buffer)
err = reg.Encode(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", reg.Hash.ReverseString())
}

View file

@ -1,43 +0,0 @@
package transaction
import (
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/version"
"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 {
*Base
Descriptors []*StateDescriptor
}
//NewStateTX returns a state transaction
func NewStateTX(ver version.TX) *StateTX {
basicTrans := createBaseTransaction(types.State, ver)
StateTX := &StateTX{}
StateTX.Base = basicTrans
StateTX.encodeExclusive = StateTX.encodeExcl
StateTX.decodeExclusive = StateTX.decodeExcl
return StateTX
}
func (s *StateTX) encodeExcl(bw *util.BinWriter) {
bw.VarUint(uint64(len(s.Descriptors)))
for _, desc := range s.Descriptors {
desc.Encode(bw)
}
}
func (s *StateTX) decodeExcl(br *util.BinReader) {
lenDesc := br.VarUint()
s.Descriptors = make([]*StateDescriptor, lenDesc)
for i := 0; i < int(lenDesc); i++ {
s.Descriptors[i] = &StateDescriptor{}
s.Descriptors[i].Decode(br)
}
}

View file

@ -1,55 +0,0 @@
package transaction
import (
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
// DescStateType represents the type of StateDescriptor.
type DescStateType uint8
// Valid DescStateType constants.
const (
Account DescStateType = 0x40
Validator DescStateType = 0x48
)
// StateDescriptor represents a state descriptor on the neo network
// used in a state transaction
type StateDescriptor struct {
Type DescStateType
Key []byte
Value []byte
Field string
}
// Decode decodes a binary reader into a state descriptor
func (s *StateDescriptor) Decode(br *util.BinReader) {
br.Read(&s.Type)
keyLen := br.VarUint()
s.Key = make([]byte, keyLen)
br.Read(s.Key)
valLen := br.VarUint()
s.Value = make([]byte, valLen)
br.Read(s.Value)
fieldLen := br.VarUint()
field := make([]byte, fieldLen)
br.Read(field)
s.Field = string(field)
}
//Encode encodes a state descriptor into a binary writer
func (s *StateDescriptor) Encode(bw *util.BinWriter) {
bw.Write(s.Type)
bw.VarUint(uint64(len(s.Key)))
bw.Write(s.Key)
bw.VarUint(uint64(len(s.Value)))
bw.Write(s.Value)
bw.VarString(s.Field)
}

View file

@ -1,63 +0,0 @@
package types
import (
"github.com/CityOfZion/neo-go/pkg/wire/util"
)
// TX is the type of a transaction.
type TX uint8
// List of transaction types
const (
Miner TX = 0x00
Issue TX = 0x01
Claim TX = 0x02
Enrollment TX = 0x20
Voting TX = 0x24
Register TX = 0x40
Contract TX = 0x80
State TX = 0x90
Agency TX = 0xb0
Publish TX = 0xd0
Invocation TX = 0xd1
)
// Encode encodes a tx type into the binary writer
func (t *TX) Encode(bw *util.BinWriter) {
bw.Write(t)
}
// Decode decodes a binary reader into a tx type
func (t *TX) Decode(br *util.BinReader) {
br.Read(t)
}
// String implements the stringer interface.
func (t TX) String() string {
switch t {
case Miner:
return "MinerTransaction"
case Issue:
return "IssueTransaction"
case Claim:
return "ClaimTransaction"
case Enrollment:
return "EnrollmentTransaction"
case Voting:
return "VotingTransaction"
case Register:
return "RegisterTransaction"
case Contract:
return "ContractTransaction"
case State:
return "StateTransaction"
case Agency:
return "AgencyTransaction"
case Publish:
return "PublishTransaction"
case Invocation:
return "InvocationTransaction"
default:
return "UnkownTransaction"
}
}

View file

@ -1,62 +0,0 @@
package transaction
import (
"bufio"
"encoding/hex"
"errors"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
)
// FromReader returns a transaction from a bufio.Reader
func FromReader(reader *bufio.Reader) (Transactioner, error) {
t, err := reader.Peek(1)
typ := types.TX(t[0])
var trans Transactioner
switch typ {
case types.Miner:
miner := NewMiner(0)
err = miner.Decode(reader)
trans = miner
case types.Contract:
contract := NewContract(0)
err = contract.Decode(reader)
trans = contract
case types.Invocation:
invoc := NewInvocation(0)
err = invoc.Decode(reader)
trans = invoc
case types.Claim:
claim := NewClaim(0)
err = claim.Decode(reader)
trans = claim
case types.Register:
reg := NewRegister(0)
err = reg.Decode(reader)
trans = reg
case types.Issue:
iss := NewIssue(0)
err = iss.Decode(reader)
trans = iss
case types.Publish:
pub := NewPublish(0)
err = pub.Decode(reader)
trans = pub
case types.State:
state := NewStateTX(0)
err = state.Decode(reader)
trans = state
case types.Enrollment:
enr := NewEnrollment(0)
err = enr.Decode(reader)
trans = enr
case types.Agency:
err = errors.New("unsupported transaction type: Agency")
default:
err = errors.New("unsupported transaction with byte type " + hex.EncodeToString([]byte{t[0]}))
}
return trans, err
}

View file

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

View file

@ -1,50 +1,6 @@
package transaction
var (
attrLookup = map[AttrUsage]string{
ContractHash: "ContractHash",
ECDH02: "ECDH02",
ECDH03: "ECDH03",
Script: "Script",
Vote: "Vote",
CertURL: "CertURL",
DescriptionURL: "DescriptionURL",
Description: "Description",
Hash1: "Hash1",
Hash2: "Hash2",
Hash3: "Hash3",
Hash4: "Hash4",
Hash5: "Hash5",
Hash6: "Hash6",
Hash7: "Hash7",
Hash8: "Hash8",
Hash9: "Hash9",
Hash10: "Hash10",
Hash11: "Hash11",
Hash12: "Hash12",
Hash13: "Hash13",
Hash14: "Hash14",
Hash15: "Hash15",
Remark: "Remark",
Remark1: "Remark1",
Remark2: "Remark2",
Remark3: "Remark3",
Remark4: "Remark4",
Remark5: "Remark5",
Remark6: "Remark6",
Remark7: "Remark7",
Remark8: "Remark8",
Remark9: "Remark9",
Remark10: "Remark10",
Remark11: "Remark11",
Remark12: "Remark12",
Remark13: "Remark13",
Remark14: "Remark14",
Remark15: "Remark15",
}
)
//go:generate stringer -type=AttrUsage
// AttrUsage represents the purpose of the attribute.
type AttrUsage uint8
@ -93,11 +49,3 @@ const (
Remark14 AttrUsage = 0xfe
Remark15 AttrUsage = 0xff
)
// String implements the stringer interface.
func (attr AttrUsage) String() string {
if v, ok := attrLookup[attr]; ok {
return v
}
return "Unkown Attribute"
}

View file

@ -36,7 +36,10 @@ func (attr *Attribute) DecodeBinary(r io.Reader) error {
case Script:
datasize = 20
case DescriptionURL:
datasize = 1
// It's not VarUint as per C# implementation, dunno why
var urllen uint8
br.ReadLE(&urllen)
datasize = uint64(urllen)
case Description, Remark, Remark1, Remark2, Remark3, Remark4,
Remark5, Remark6, Remark7, Remark8, Remark9, Remark10, Remark11,
Remark12, Remark13, Remark14, Remark15:
@ -56,10 +59,13 @@ func (attr *Attribute) EncodeBinary(w io.Writer) error {
switch attr.Usage {
case ECDH02, ECDH03:
bw.WriteLE(attr.Data[1:])
case DescriptionURL, Description, Remark, Remark1, Remark2, Remark3, Remark4,
case Description, Remark, Remark1, Remark2, Remark3, Remark4,
Remark5, Remark6, Remark7, Remark8, Remark9, Remark10, Remark11,
Remark12, Remark13, Remark14, Remark15:
bw.WriteVarUint(uint64(len(attr.Data)))
bw.WriteBytes(attr.Data)
case DescriptionURL:
var urllen uint8 = uint8(len(attr.Data))
bw.WriteLE(urllen)
fallthrough
case Script, ContractHash, Vote, Hash1, Hash2, Hash3, Hash4, Hash5, Hash6,
Hash7, Hash8, Hash9, Hash10, Hash11, Hash12, Hash13, Hash14, Hash15:
@ -81,7 +87,7 @@ func (attr *Attribute) Size() int {
case Script:
sz += 20 // uint8 + 20 = size(attrUsage) + 20
case DescriptionURL:
sz += 1
sz += 1 + len(attr.Data)
default:
sz += util.GetVarSize(attr.Data)
}

View file

@ -0,0 +1,95 @@
// Code generated by "stringer -type=AttrUsage"; DO NOT EDIT.
package transaction
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ContractHash-0]
_ = x[ECDH02-2]
_ = x[ECDH03-3]
_ = x[Script-32]
_ = x[Vote-48]
_ = x[CertURL-128]
_ = x[DescriptionURL-129]
_ = x[Description-144]
_ = x[Hash1-161]
_ = x[Hash2-162]
_ = x[Hash3-163]
_ = x[Hash4-164]
_ = x[Hash5-165]
_ = x[Hash6-166]
_ = x[Hash7-167]
_ = x[Hash8-168]
_ = x[Hash9-169]
_ = x[Hash10-170]
_ = x[Hash11-171]
_ = x[Hash12-172]
_ = x[Hash13-173]
_ = x[Hash14-174]
_ = x[Hash15-175]
_ = x[Remark-240]
_ = x[Remark1-241]
_ = x[Remark2-242]
_ = x[Remark3-243]
_ = x[Remark4-244]
_ = x[Remark5-245]
_ = x[Remark6-246]
_ = x[Remark7-247]
_ = x[Remark8-248]
_ = x[Remark9-249]
_ = x[Remark10-250]
_ = x[Remark11-251]
_ = x[Remark12-252]
_ = x[Remark13-253]
_ = x[Remark14-254]
_ = x[Remark15-255]
}
const (
_AttrUsage_name_0 = "ContractHash"
_AttrUsage_name_1 = "ECDH02ECDH03"
_AttrUsage_name_2 = "Script"
_AttrUsage_name_3 = "Vote"
_AttrUsage_name_4 = "CertURLDescriptionURL"
_AttrUsage_name_5 = "Description"
_AttrUsage_name_6 = "Hash1Hash2Hash3Hash4Hash5Hash6Hash7Hash8Hash9Hash10Hash11Hash12Hash13Hash14Hash15"
_AttrUsage_name_7 = "RemarkRemark1Remark2Remark3Remark4Remark5Remark6Remark7Remark8Remark9Remark10Remark11Remark12Remark13Remark14Remark15"
)
var (
_AttrUsage_index_1 = [...]uint8{0, 6, 12}
_AttrUsage_index_4 = [...]uint8{0, 7, 21}
_AttrUsage_index_6 = [...]uint8{0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 51, 57, 63, 69, 75, 81}
_AttrUsage_index_7 = [...]uint8{0, 6, 13, 20, 27, 34, 41, 48, 55, 62, 69, 77, 85, 93, 101, 109, 117}
)
func (i AttrUsage) String() string {
switch {
case i == 0:
return _AttrUsage_name_0
case 2 <= i && i <= 3:
i -= 2
return _AttrUsage_name_1[_AttrUsage_index_1[i]:_AttrUsage_index_1[i+1]]
case i == 32:
return _AttrUsage_name_2
case i == 48:
return _AttrUsage_name_3
case 128 <= i && i <= 129:
i -= 128
return _AttrUsage_name_4[_AttrUsage_index_4[i]:_AttrUsage_index_4[i+1]]
case i == 144:
return _AttrUsage_name_5
case 161 <= i && i <= 175:
i -= 161
return _AttrUsage_name_6[_AttrUsage_index_6[i]:_AttrUsage_index_6[i+1]]
case 240 <= i && i <= 255:
i -= 240
return _AttrUsage_name_7[_AttrUsage_index_7[i]:_AttrUsage_index_7[i+1]]
default:
return "AttrUsage(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View file

@ -5,8 +5,6 @@ import (
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/stretchr/testify/assert"
)
@ -14,32 +12,26 @@ func TestEncodeDecodeContract(t *testing.T) {
// mainnet transaction: bdf6cc3b9af12a7565bda80933a75ee8cef1bc771d0d58effc08e4c8b436da79
rawtx := "80000001888da99f8f497fd65c4325786a09511159c279af4e7eb532e9edd628c87cc1ee0000019b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50082167010000000a8666b4830229d6a1a9b80f6088059191c122d2b0141409e79e132290c82916a88f1a3db5cf9f3248b780cfece938ab0f0812d0e188f3a489c7d1a23def86bd69d863ae67de753b2c2392e9497eadc8eb9fc43aa52c645232103e2f6a334e05002624cf616f01a62cff2844c34a3b08ca16048c259097e315078ac"
rawtxBytes, _ := hex.DecodeString(rawtx)
c := NewContract(30)
tx := decodeTransaction(rawtx, t)
r := bytes.NewReader(rawtxBytes)
err := c.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, ContractType, tx.Type)
assert.IsType(t, tx.Data, &ContractTX{})
assert.Equal(t, 0, int(tx.Version))
assert.Equal(t, 1, int(len(tx.Inputs)))
assert.Equal(t, types.Contract, c.Type)
assert.Equal(t, 0, int(c.Version))
assert.Equal(t, 1, int(len(c.Inputs)))
input := c.Inputs[0]
input := tx.Inputs[0]
assert.Equal(t, "eec17cc828d6ede932b57e4eaf79c2591151096a7825435cd67f498f9fa98d88", input.PrevHash.ReverseString())
assert.Equal(t, 0, int(input.PrevIndex))
assert.Equal(t, int64(70600000000), c.Outputs[0].Amount)
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", c.Outputs[0].AssetID.ReverseString())
assert.Equal(t, "a8666b4830229d6a1a9b80f6088059191c122d2b", c.Outputs[0].ScriptHash.String())
assert.Equal(t, "bdf6cc3b9af12a7565bda80933a75ee8cef1bc771d0d58effc08e4c8b436da79", c.Hash.ReverseString())
assert.Equal(t, int64(706), tx.Outputs[0].Amount.Int64Value())
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Outputs[0].AssetID.ReverseString())
assert.Equal(t, "a8666b4830229d6a1a9b80f6088059191c122d2b", tx.Outputs[0].ScriptHash.String())
assert.Equal(t, "bdf6cc3b9af12a7565bda80933a75ee8cef1bc771d0d58effc08e4c8b436da79", tx.Hash().ReverseString())
// Encode
buf := new(bytes.Buffer)
err = c.Encode(buf)
err := tx.EncodeBinary(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtxBytes, buf.Bytes())
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}

View file

@ -1,6 +1,24 @@
package transaction
import "testing"
import (
"bytes"
"encoding/hex"
"testing"
func TestDecodeEncode(t *testing.T) {
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeEnrollment(t *testing.T) {
rawtx := "200002ff8ac54687f36bbc31a91b730cc385da8af0b581f2d59d82b5cfef824fd271f60001d3d3b7028d61fea3b7803fda3d7f0a1f7262d38e5e1c8987b0313e0a94574151000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c60005441d11600000050ac4949596f5b62fef7be4d1c3e494e6048ed4a01414079d78189d591097b17657a62240c93595e8233dc81157ea2cd477813f09a11fd72845e6bd97c5a3dda125985ea3d5feca387e9933649a9a671a69ab3f6301df6232102ff8ac54687f36bbc31a91b730cc385da8af0b581f2d59d82b5cfef824fd271f6ac"
tx := decodeTransaction(rawtx, t)
assert.Equal(t, "988832f693785dcbcb8d5a0e9d5d22002adcbfb1eb6bbeebf8c494fff580e147", tx.Hash().ReverseString())
assert.Equal(t, EnrollmentType, tx.Type)
assert.IsType(t, tx.Data, &EnrollmentTX{})
assert.Equal(t, 0, int(tx.Version))
buf := new(bytes.Buffer)
err := tx.EncodeBinary(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}

View file

@ -5,33 +5,26 @@ import (
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeMiner(t *testing.T) {
// transaction from mainnet a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264
rawtx := "0000fcd30e22000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c60c8000000000000001f72e68b4e39602912106d53b229378a082784b200"
rawtxBytes, _ := hex.DecodeString(rawtx)
m := NewMiner(0)
r := bytes.NewReader(rawtxBytes)
err := m.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, types.Miner, m.Type)
tx := decodeTransaction(rawtx, t)
assert.Equal(t, MinerType, tx.Type)
assert.IsType(t, tx.Data, &MinerTX{})
assert.Equal(t, 0, int(tx.Version))
m := tx.Data.(*MinerTX)
assert.Equal(t, uint32(571397116), m.Nonce)
assert.Equal(t, "a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264", m.Hash.ReverseString())
assert.Equal(t, "a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264", tx.Hash().ReverseString())
// Encode
buf := new(bytes.Buffer)
err = m.Encode(buf)
err := tx.EncodeBinary(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtxBytes, buf.Bytes())
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}

View file

@ -56,7 +56,22 @@ func (tx *PublishTX) DecodeBinary(r io.Reader) error {
// EncodeBinary implements the Payload interface.
func (tx *PublishTX) EncodeBinary(w io.Writer) error {
return nil
bw := util.BinWriter{W: w}
bw.WriteBytes(tx.Script)
bw.WriteVarUint(uint64(len(tx.ParamList)))
for _, param := range tx.ParamList {
bw.WriteLE(uint8(param))
}
bw.WriteLE(uint8(tx.ReturnType))
if tx.Version >= 1 {
bw.WriteLE(tx.NeedStorage)
}
bw.WriteString(tx.Name)
bw.WriteString(tx.CodeVersion)
bw.WriteString(tx.Author)
bw.WriteString(tx.Email)
bw.WriteString(tx.Description)
return bw.Err
}
func (tx *PublishTX) Size() int {

View file

@ -18,6 +18,7 @@ func (tx *StateTX) DecodeBinary(r io.Reader) error {
if br.Err != nil {
return br.Err
}
tx.Descriptors = make([]*StateDescriptor, lenDesc)
for i := 0; i < int(lenDesc); i++ {
tx.Descriptors[i] = &StateDescriptor{}
if err := tx.Descriptors[i].DecodeBinary(r); err != nil {
@ -29,6 +30,17 @@ func (tx *StateTX) DecodeBinary(r io.Reader) error {
// EncodeBinary implements the Payload interface.
func (tx *StateTX) EncodeBinary(w io.Writer) error {
bw := util.BinWriter{W: w}
bw.WriteVarUint(uint64(len(tx.Descriptors)))
if bw.Err != nil {
return bw.Err
}
for _, desc := range tx.Descriptors {
err := desc.EncodeBinary(w)
if err != nil {
return err
}
}
return nil
}

View file

@ -37,7 +37,12 @@ func (s *StateDescriptor) DecodeBinary(r io.Reader) error {
// EncodeBinary implements the Payload interface.
func (s *StateDescriptor) EncodeBinary(w io.Writer) error {
return nil
bw := util.BinWriter{W: w}
bw.WriteLE(s.Type)
bw.WriteBytes(s.Key)
bw.WriteBytes(s.Value)
bw.WriteString(s.Field)
return bw.Err
}
func (s *StateDescriptor) Size() int {

View file

@ -5,29 +5,23 @@ import (
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeState(t *testing.T) {
// transaction taken from testnet 8abf5ebdb9a8223b12109513647f45bd3c0a6cf1a6346d56684cff71ba308724
rawtx := "900001482103c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c10a5265676973746572656401010001cb4184f0a96e72656c1fbdd4f75cca567519e909fd43cefcec13d6c6abcb92a1000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6000b8fb050109000071f9cf7f0ec74ec0b0f28a92b12e1081574c0af00141408780d7b3c0aadc5398153df5e2f1cf159db21b8b0f34d3994d865433f79fafac41683783c48aef510b67660e3157b701b9ca4dd9946a385d578fba7dd26f4849232103c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c1ac"
rawtxBytes, _ := hex.DecodeString(rawtx)
tx := decodeTransaction(rawtx, t)
assert.Equal(t, StateType, tx.Type)
assert.IsType(t, tx.Data, &StateTX{})
assert.Equal(t, "8abf5ebdb9a8223b12109513647f45bd3c0a6cf1a6346d56684cff71ba308724", tx.Hash().ReverseString())
s := NewStateTX(0)
r := bytes.NewReader(rawtxBytes)
err := s.Decode(r)
assert.Equal(t, nil, err)
assert.Equal(t, types.State, s.Type)
assert.Equal(t, 1, len(s.Inputs))
input := s.Inputs[0]
assert.Equal(t, 1, len(tx.Inputs))
input := tx.Inputs[0]
assert.Equal(t, "a192cbabc6d613ecfcce43fd09e9197556ca5cf7d4bd1f6c65726ea9f08441cb", input.PrevHash.ReverseString())
assert.Equal(t, uint16(0), input.PrevIndex)
s := tx.Data.(*StateTX)
assert.Equal(t, 1, len(s.Descriptors))
descriptor := s.Descriptors[0]
assert.Equal(t, "03c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c1", hex.EncodeToString(descriptor.Key))
@ -39,9 +33,8 @@ func TestEncodeDecodeState(t *testing.T) {
buf := new(bytes.Buffer)
err = s.Encode(buf)
err := tx.EncodeBinary(buf)
assert.Equal(t, nil, err)
assert.Equal(t, rawtxBytes, buf.Bytes())
assert.Equal(t, "8abf5ebdb9a8223b12109513647f45bd3c0a6cf1a6346d56684cff71ba308724", s.Hash.ReverseString())
assert.Equal(t, rawtx, hex.EncodeToString(buf.Bytes()))
}

View file

@ -144,4 +144,9 @@ func TestDecodePublishTX(t *testing.T) {
assert.Equal(t, expectedTX.Data, actualTX.Data)
assert.Equal(t, expectedTX.Type, actualTX.Type)
assert.Equal(t, expectedTX.Version, actualTX.Version)
buf := new(bytes.Buffer)
err := actualTX.EncodeBinary(buf)
assert.Nil(t, err)
assert.Equal(t, rawPublishTX, hex.EncodeToString(buf.Bytes()))
}