pkg: hide it by moving to _pkg.dev
The idea here is to preserve the history of `dev` branch development and its code when merging with the `master`. Later this code could be moved into the masters code where appropriate.
This commit is contained in:
parent
bb2568cc53
commit
ddd1d92ff1
183 changed files with 0 additions and 0 deletions
67
_pkg.dev/wire/payload/block.go
Normal file
67
_pkg.dev/wire/payload/block.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
)
|
||||
|
||||
// Block representa a Block in the neo-network
|
||||
type Block struct {
|
||||
BlockBase
|
||||
Txs []transaction.Transactioner
|
||||
}
|
||||
|
||||
// Decode decodes an io.Reader into a Block
|
||||
func (b *Block) Decode(r io.Reader) error {
|
||||
br := &util.BinReader{R: r}
|
||||
b.DecodePayload(br)
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// Encode writes a block into a io.Writer
|
||||
func (b *Block) Encode(w io.Writer) error {
|
||||
bw := &util.BinWriter{W: w}
|
||||
b.EncodePayload(bw)
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
//EncodePayload implements Messager interface
|
||||
func (b *Block) EncodePayload(bw *util.BinWriter) {
|
||||
b.BlockBase.EncodePayload(bw)
|
||||
bw.VarUint(uint64(len(b.Txs)))
|
||||
for _, tx := range b.Txs {
|
||||
tx.Encode(bw.W)
|
||||
}
|
||||
}
|
||||
|
||||
// DecodePayload implements Messager interface
|
||||
func (b *Block) DecodePayload(br *util.BinReader) error {
|
||||
|
||||
b.BlockBase.DecodePayload(br)
|
||||
lenTXs := br.VarUint()
|
||||
|
||||
b.Txs = make([]transaction.Transactioner, lenTXs)
|
||||
|
||||
reader := bufio.NewReader(br.R)
|
||||
for i := 0; i < int(lenTXs); i++ {
|
||||
|
||||
tx, err := transaction.FromReader(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.Txs[i] = tx
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bytes returns the Byte representation of Block
|
||||
func (b *Block) Bytes() ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
err := b.Encode(buf)
|
||||
return buf.Bytes(), err
|
||||
}
|
172
_pkg.dev/wire/payload/block_test.go
Normal file
172
_pkg.dev/wire/payload/block_test.go
Normal file
File diff suppressed because one or more lines are too long
132
_pkg.dev/wire/payload/blockbase.go
Normal file
132
_pkg.dev/wire/payload/blockbase.go
Normal file
|
@ -0,0 +1,132 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
)
|
||||
|
||||
var (
|
||||
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 {
|
||||
// Version of the block.
|
||||
Version uint32 `json:"version"`
|
||||
|
||||
// hash of the previous block.
|
||||
PrevHash util.Uint256 `json:"previousblockhash"`
|
||||
|
||||
// Root hash of a transaction list.
|
||||
MerkleRoot util.Uint256 `json:"merkleroot"`
|
||||
|
||||
// The time stamp of each block must be later than previous block's time stamp.
|
||||
// Generally the difference of two block's time stamp is about 15 seconds and imprecision is allowed.
|
||||
// The height of the block must be exactly equal to the height of the previous block plus 1.
|
||||
Timestamp uint32 `json:"time"`
|
||||
|
||||
// index/height of the block
|
||||
Index uint32 `json:"height"`
|
||||
|
||||
// Random number also called nonce
|
||||
ConsensusData uint64 `json:"nonce"`
|
||||
|
||||
// Contract addresss of the next miner
|
||||
NextConsensus util.Uint160 `json:"next_consensus"`
|
||||
|
||||
// Padding that is fixed to 1
|
||||
_ uint8
|
||||
|
||||
// Script used to validate the block
|
||||
Witness transaction.Witness `json:"script"`
|
||||
|
||||
// hash of this block, created when binary encoded.
|
||||
Hash util.Uint256
|
||||
}
|
||||
|
||||
// EncodePayload implements the Messager interface
|
||||
func (b *BlockBase) EncodePayload(bw *util.BinWriter) error {
|
||||
|
||||
b.encodeHashableFields(bw)
|
||||
|
||||
bw.Write(uint8(1))
|
||||
b.Witness.Encode(bw)
|
||||
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Decode decodes an io.Reader into a Blockbase
|
||||
func (b *BlockBase) Decode(r io.Reader) error {
|
||||
br := &util.BinReader{R: r}
|
||||
b.DecodePayload(br)
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// Encode encodes a blockbase into an io.Writer
|
||||
func (b *BlockBase) Encode(w io.Writer) error {
|
||||
bw := &util.BinWriter{W: w}
|
||||
b.EncodePayload(bw)
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
func (b *BlockBase) encodeHashableFields(bw *util.BinWriter) {
|
||||
bw.Write(b.Version)
|
||||
bw.Write(b.PrevHash)
|
||||
bw.Write(b.MerkleRoot)
|
||||
bw.Write(b.Timestamp)
|
||||
bw.Write(b.Index)
|
||||
bw.Write(b.ConsensusData)
|
||||
bw.Write(b.NextConsensus)
|
||||
}
|
||||
|
||||
// DecodePayload implements the messager interface
|
||||
func (b *BlockBase) DecodePayload(br *util.BinReader) error {
|
||||
|
||||
b.decodeHashableFields(br)
|
||||
|
||||
var padding uint8
|
||||
br.Read(&padding)
|
||||
if padding != 1 {
|
||||
return errPadding
|
||||
}
|
||||
|
||||
b.Witness = transaction.Witness{}
|
||||
b.Witness.Decode(br)
|
||||
|
||||
err := b.createHash()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return br.Err
|
||||
}
|
||||
|
||||
func (b *BlockBase) decodeHashableFields(br *util.BinReader) {
|
||||
br.Read(&b.Version)
|
||||
br.Read(&b.PrevHash)
|
||||
br.Read(&b.MerkleRoot)
|
||||
br.Read(&b.Timestamp)
|
||||
br.Read(&b.Index)
|
||||
br.Read(&b.ConsensusData)
|
||||
br.Read(&b.NextConsensus)
|
||||
}
|
||||
|
||||
func (b *BlockBase) createHash() error {
|
||||
|
||||
hash, err := util.CalculateHash(b.encodeHashableFields)
|
||||
b.Hash = hash
|
||||
return err
|
||||
}
|
||||
|
||||
// Bytes returns the byte representation of Blockbase
|
||||
func (b *BlockBase) Bytes() ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
err := b.Encode(buf)
|
||||
return buf.Bytes(), err
|
||||
}
|
8
_pkg.dev/wire/payload/blockbase_test.go
Normal file
8
_pkg.dev/wire/payload/blockbase_test.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
package payload
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test(t *testing.T) {
|
||||
//tests for this have been included in the mheaders_test file
|
||||
|
||||
}
|
64
_pkg.dev/wire/payload/maddr.go
Normal file
64
_pkg.dev/wire/payload/maddr.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
)
|
||||
|
||||
// AddrMessage represents an address message on the neo network
|
||||
type AddrMessage struct {
|
||||
AddrList []*NetAddr
|
||||
}
|
||||
|
||||
// NewAddrMessage instantiates a new AddrMessage
|
||||
func NewAddrMessage() (*AddrMessage, error) {
|
||||
addrMess := &AddrMessage{
|
||||
nil,
|
||||
}
|
||||
return addrMess, nil
|
||||
}
|
||||
|
||||
// AddNetAddr will add a net address into the Address message
|
||||
func (a *AddrMessage) AddNetAddr(n *NetAddr) error {
|
||||
a.AddrList = append(a.AddrList, n)
|
||||
// TODO:check if max reached, if so return err. What is max?
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (a *AddrMessage) DecodePayload(r io.Reader) error {
|
||||
|
||||
br := &util.BinReader{R: r}
|
||||
listLen := br.VarUint()
|
||||
|
||||
a.AddrList = make([]*NetAddr, listLen)
|
||||
for i := 0; i < int(listLen); i++ {
|
||||
a.AddrList[i] = &NetAddr{}
|
||||
a.AddrList[i].DecodePayload(br)
|
||||
if br.Err != nil {
|
||||
return br.Err
|
||||
}
|
||||
}
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (a *AddrMessage) EncodePayload(w io.Writer) error {
|
||||
bw := &util.BinWriter{W: w}
|
||||
|
||||
listLen := uint64(len(a.AddrList))
|
||||
bw.VarUint(listLen)
|
||||
|
||||
for _, addr := range a.AddrList {
|
||||
addr.EncodePayload(bw)
|
||||
}
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Command Implements messager interface
|
||||
func (a *AddrMessage) Command() command.Type {
|
||||
return command.Addr
|
||||
}
|
40
_pkg.dev/wire/payload/maddr_test.go
Normal file
40
_pkg.dev/wire/payload/maddr_test.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util/Checksum"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/protocol"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAddrMessageEncodeDecode(t *testing.T) {
|
||||
|
||||
ip := []byte(net.ParseIP("127.0.0.1").To16())
|
||||
|
||||
var ipByte [16]byte
|
||||
copy(ipByte[:], ip)
|
||||
|
||||
netaddr, err := NewNetAddr(uint32(time.Now().Unix()), ipByte, 8080, protocol.NodePeerService)
|
||||
addrmsg, err := NewAddrMessage()
|
||||
addrmsg.AddNetAddr(netaddr)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err = addrmsg.EncodePayload(buf)
|
||||
expected := checksum.FromBuf(buf)
|
||||
|
||||
addrmsgDec, err := NewAddrMessage()
|
||||
r := bytes.NewReader(buf.Bytes())
|
||||
err = addrmsgDec.DecodePayload(r)
|
||||
|
||||
buf = new(bytes.Buffer)
|
||||
err = addrmsgDec.EncodePayload(buf)
|
||||
have := checksum.FromBuf(buf)
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, expected, have)
|
||||
}
|
38
_pkg.dev/wire/payload/mblock.go
Normal file
38
_pkg.dev/wire/payload/mblock.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
)
|
||||
|
||||
// BlockMessage represents a block message on the neo-network
|
||||
type BlockMessage struct {
|
||||
Block
|
||||
}
|
||||
|
||||
// NewBlockMessage will return a block message object
|
||||
func NewBlockMessage() (*BlockMessage, error) {
|
||||
return &BlockMessage{}, nil
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (b *BlockMessage) DecodePayload(r io.Reader) error {
|
||||
br := &util.BinReader{R: r}
|
||||
b.Block.DecodePayload(br)
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (b *BlockMessage) EncodePayload(w io.Writer) error {
|
||||
bw := &util.BinWriter{W: w}
|
||||
b.Block.EncodePayload(bw)
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Command Implements messager interface
|
||||
func (b *BlockMessage) Command() command.Type {
|
||||
return command.Block
|
||||
}
|
30
_pkg.dev/wire/payload/mgetaddr.go
Normal file
30
_pkg.dev/wire/payload/mgetaddr.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
)
|
||||
|
||||
//GetAddrMessage represents a GetAddress message on the neo-network
|
||||
type GetAddrMessage struct{}
|
||||
|
||||
// NewGetAddrMessage returns a GetAddrMessage object
|
||||
func NewGetAddrMessage() (*GetAddrMessage, error) {
|
||||
return &GetAddrMessage{}, nil
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (v *GetAddrMessage) DecodePayload(r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (v *GetAddrMessage) EncodePayload(w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Command Implements messager interface
|
||||
func (v *GetAddrMessage) Command() command.Type {
|
||||
return command.GetAddr
|
||||
}
|
24
_pkg.dev/wire/payload/mgetaddr_test.go
Normal file
24
_pkg.dev/wire/payload/mgetaddr_test.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util/Checksum"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewGetAddr(t *testing.T) {
|
||||
|
||||
getAddrMessage, err := NewGetAddrMessage()
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
assert.Equal(t, command.GetAddr, getAddrMessage.Command())
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
assert.Equal(t, int(3806393949), int(checksum.FromBuf(buf)))
|
||||
assert.Equal(t, int(0), len(buf.Bytes()))
|
||||
}
|
24
_pkg.dev/wire/payload/mgetblocks.go
Normal file
24
_pkg.dev/wire/payload/mgetblocks.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
)
|
||||
|
||||
// GetBlocksMessage represnts a GetBlocks message on the neo-network
|
||||
type GetBlocksMessage struct {
|
||||
*GetHeadersMessage
|
||||
}
|
||||
|
||||
// NewGetBlocksMessage returns a GetBlocksMessage object
|
||||
func NewGetBlocksMessage(start []util.Uint256, stop util.Uint256) (*GetBlocksMessage, error) {
|
||||
GetHeaders, err := newAbstractGetHeaders(start, stop, command.GetBlocks)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &GetBlocksMessage{
|
||||
GetHeaders,
|
||||
}, nil
|
||||
|
||||
}
|
27
_pkg.dev/wire/payload/mgetblocks_test.go
Normal file
27
_pkg.dev/wire/payload/mgetblocks_test.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetBlocksCommandType(t *testing.T) {
|
||||
var (
|
||||
start = []util.Uint256{
|
||||
sha256.Sum256([]byte("a")),
|
||||
sha256.Sum256([]byte("b")),
|
||||
sha256.Sum256([]byte("c")),
|
||||
sha256.Sum256([]byte("d")),
|
||||
}
|
||||
stop = sha256.Sum256([]byte("e"))
|
||||
)
|
||||
|
||||
getBlocks, err := NewGetBlocksMessage(start, stop)
|
||||
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, command.GetBlocks, getBlocks.Command())
|
||||
}
|
18
_pkg.dev/wire/payload/mgetdata.go
Normal file
18
_pkg.dev/wire/payload/mgetdata.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
)
|
||||
|
||||
// GetDataMessage represents a GetData message on the neo-network
|
||||
type GetDataMessage struct {
|
||||
*InvMessage
|
||||
}
|
||||
|
||||
//NewGetDataMessage returns a GetDataMessage object
|
||||
func NewGetDataMessage(typ InvType) (*GetDataMessage, error) {
|
||||
getData, err := newAbstractInv(typ, command.GetData)
|
||||
return &GetDataMessage{
|
||||
getData,
|
||||
}, err
|
||||
}
|
19
_pkg.dev/wire/payload/mgetdata_test.go
Normal file
19
_pkg.dev/wire/payload/mgetdata_test.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetDataCommandType(t *testing.T) {
|
||||
getData, err := NewGetDataMessage(InvTypeBlock)
|
||||
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, command.GetData, getData.Command())
|
||||
}
|
||||
|
||||
func TestOtherFunctions(t *testing.T) {
|
||||
// Other capabilities are tested in the inherited struct
|
||||
}
|
61
_pkg.dev/wire/payload/mgetheaders.go
Normal file
61
_pkg.dev/wire/payload/mgetheaders.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
)
|
||||
|
||||
//GetHeadersMessage represents a GetHeaders message on the neo-network
|
||||
type GetHeadersMessage struct {
|
||||
cmd command.Type
|
||||
hashStart []util.Uint256
|
||||
hashStop util.Uint256
|
||||
}
|
||||
|
||||
// NewGetHeadersMessage returns a NewGetHeaders object
|
||||
// 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
|
||||
func NewGetHeadersMessage(start []util.Uint256, stop util.Uint256) (*GetHeadersMessage, error) {
|
||||
getHeaders := &GetHeadersMessage{command.GetHeaders, start, stop}
|
||||
|
||||
return getHeaders, nil
|
||||
|
||||
}
|
||||
|
||||
func newAbstractGetHeaders(start []util.Uint256, stop util.Uint256, cmd command.Type) (*GetHeadersMessage, error) {
|
||||
getHeaders, err := NewGetHeadersMessage(start, stop)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
getHeaders.cmd = cmd
|
||||
return getHeaders, nil
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (v *GetHeadersMessage) DecodePayload(r io.Reader) error {
|
||||
|
||||
br := util.BinReader{R: r}
|
||||
lenStart := br.VarUint()
|
||||
v.hashStart = make([]util.Uint256, lenStart)
|
||||
br.Read(&v.hashStart)
|
||||
br.Read(&v.hashStop)
|
||||
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (v *GetHeadersMessage) EncodePayload(w io.Writer) error {
|
||||
bw := &util.BinWriter{W: w}
|
||||
bw.VarUint(uint64(len(v.hashStart)))
|
||||
bw.Write(v.hashStart)
|
||||
bw.Write(v.hashStop)
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Command Implements messager interface
|
||||
func (v *GetHeadersMessage) Command() command.Type {
|
||||
return v.cmd
|
||||
}
|
47
_pkg.dev/wire/payload/mgetheaders_test.go
Normal file
47
_pkg.dev/wire/payload/mgetheaders_test.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util/Checksum"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Test taken from neo-go v1
|
||||
func TestGetHeadersEncodeDecode(t *testing.T) {
|
||||
|
||||
var (
|
||||
start = []util.Uint256{
|
||||
sha256.Sum256([]byte("a")),
|
||||
sha256.Sum256([]byte("b")),
|
||||
sha256.Sum256([]byte("c")),
|
||||
sha256.Sum256([]byte("d")),
|
||||
}
|
||||
stop = sha256.Sum256([]byte("e"))
|
||||
)
|
||||
msgGetHeaders, err := NewGetHeadersMessage(start, stop)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
err = msgGetHeaders.EncodePayload(buf)
|
||||
assert.Equal(t, nil, err)
|
||||
expected := checksum.FromBuf(buf)
|
||||
|
||||
msgGetHeadersDec, err := NewGetHeadersMessage([]util.Uint256{}, util.Uint256{})
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
r := bytes.NewReader(buf.Bytes())
|
||||
err = msgGetHeadersDec.DecodePayload(r)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
buf = new(bytes.Buffer)
|
||||
err = msgGetHeadersDec.EncodePayload(buf)
|
||||
have := checksum.FromBuf(buf)
|
||||
|
||||
assert.Equal(t, expected, have)
|
||||
}
|
82
_pkg.dev/wire/payload/mheaders.go
Normal file
82
_pkg.dev/wire/payload/mheaders.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
)
|
||||
|
||||
// HeadersMessage represents a Header(s) Message on the neo-network
|
||||
type HeadersMessage struct {
|
||||
Headers []*BlockBase
|
||||
|
||||
// Padding that is fixed to 0
|
||||
_ uint8
|
||||
}
|
||||
|
||||
// Users can at most request 2k header
|
||||
const (
|
||||
maxHeadersAllowed = 2000
|
||||
)
|
||||
|
||||
var (
|
||||
errMaxHeaders = errors.New("Maximum amount of headers allowed is 2000")
|
||||
)
|
||||
|
||||
//NewHeadersMessage returns a HeadersMessage Object
|
||||
func NewHeadersMessage() (*HeadersMessage, error) {
|
||||
|
||||
headers := &HeadersMessage{nil, 0}
|
||||
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 {
|
||||
if len(h.Headers)+1 > maxHeadersAllowed {
|
||||
return errMaxHeaders
|
||||
}
|
||||
h.Headers = append(h.Headers, head)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (h *HeadersMessage) DecodePayload(r io.Reader) error {
|
||||
|
||||
br := &util.BinReader{R: r}
|
||||
|
||||
lenHeaders := br.VarUint()
|
||||
h.Headers = make([]*BlockBase, lenHeaders)
|
||||
|
||||
for i := 0; i < int(lenHeaders); i++ {
|
||||
header := &BlockBase{}
|
||||
header.DecodePayload(br)
|
||||
var padding uint8
|
||||
br.Read(&padding)
|
||||
if padding != 0 {
|
||||
return errPadding
|
||||
}
|
||||
h.Headers[i] = header
|
||||
}
|
||||
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (h *HeadersMessage) EncodePayload(w io.Writer) error {
|
||||
bw := &util.BinWriter{W: w}
|
||||
bw.VarUint(uint64(len(h.Headers)))
|
||||
for _, header := range h.Headers {
|
||||
header.EncodePayload(bw)
|
||||
bw.Write(uint8(0))
|
||||
}
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Command Implements messager interface
|
||||
func (h *HeadersMessage) Command() command.Type {
|
||||
return command.Headers
|
||||
}
|
82
_pkg.dev/wire/payload/mheaders_test.go
Normal file
82
_pkg.dev/wire/payload/mheaders_test.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util/address"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewHeaderMessage(t *testing.T) {
|
||||
msgHeaders, err := NewHeadersMessage()
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, 0, len(msgHeaders.Headers))
|
||||
|
||||
}
|
||||
|
||||
func TestAddAndEncodeHeaders(t *testing.T) {
|
||||
|
||||
// uses block10 from mainnet
|
||||
|
||||
msgHeaders, _ := NewHeadersMessage()
|
||||
|
||||
prevH, _ := util.Uint256DecodeString("005fb74a6de169ce5daf59a114405e5b27238b2489690e3b2a60c14ddfc3b326")
|
||||
merkleRoot, _ := util.Uint256DecodeString("ca6d58bcb837472c2f77877e68495b83fd5b714dfe0c8230a525f4511a3239f4")
|
||||
invocationScript, _ := hex.DecodeString("4036fdd23248880c1c311bcd97df04fe6d740dc1bf340c26915f0466e31e81c039012eca7a760270389e04b58b99820fe49cf8c24c9afc65d696b4d3f406a1e6b5405172a9b461e68dd399c8716de11d31f7dd2ec3be327c636b024562db6ac5df1cffdbee74c994736fd49803234d2baffbc0054f28ba5ec76494a467b4106955bb4084af7746d269241628c667003e9d39288b190ad5cef218ada625cbba8be411bb153828d8d3634e8f586638e2448425bc5b671be69800392ccbdebc945a5099c7406f6a11824105ecad345e525957053e77fbc0119d6b3fa7f854527e816cfce0d95dac66888e07e8990c95103d8e46124aac16f152e088520d7ec8325e3a2456f840e5b77ef0e3c410b347ccaf8a87516d10b88d436563c80712153273993afc320ec49b638225f58de464a1345e62a564b398939f96f6f4b7cf21b583609f85495a")
|
||||
verificationScript, _ := hex.DecodeString("552102486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a7021024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d2102aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e2103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c2103b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a2102ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba5542102df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e89509357ae")
|
||||
nextCon, _ := util.Uint160DecodeString(address.ToScriptHash("APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR"))
|
||||
|
||||
msgHeaders.AddHeader(&BlockBase{
|
||||
Version: 0,
|
||||
Index: 10,
|
||||
PrevHash: prevH.Reverse(),
|
||||
MerkleRoot: merkleRoot.Reverse(),
|
||||
Timestamp: 1476647551,
|
||||
ConsensusData: 0xc0f0280216ff14bf,
|
||||
NextConsensus: nextCon,
|
||||
Witness: transaction.Witness{
|
||||
InvocationScript: invocationScript,
|
||||
VerificationScript: verificationScript,
|
||||
},
|
||||
})
|
||||
|
||||
assert.Equal(t, 1, len(msgHeaders.Headers))
|
||||
|
||||
err := msgHeaders.Headers[0].createHash()
|
||||
assert.Equal(t, nil, err)
|
||||
// Hash being correct, automatically verifies that the fields are encoded properly
|
||||
assert.Equal(t, "f3c4ec44c07eccbda974f1ee34bc6654ab6d3f22cd89c2e5c593a16d6cc7e6e8", msgHeaders.Headers[0].Hash.ReverseString())
|
||||
|
||||
}
|
||||
|
||||
func TestEncodeDecode(t *testing.T) {
|
||||
rawBlockHeaders := "010000000026b3c3df4dc1602a3b0e6989248b23275b5e4014a159af5dce69e16d4ab75f00f439321a51f425a530820cfe4d715bfd835b49687e87772f2c4737b8bc586dca7fda03580a000000bf14ff160228f0c059e75d652b5d3827bf04c165bbe9ef95cca4bf5501fd45014036fdd23248880c1c311bcd97df04fe6d740dc1bf340c26915f0466e31e81c039012eca7a760270389e04b58b99820fe49cf8c24c9afc65d696b4d3f406a1e6b5405172a9b461e68dd399c8716de11d31f7dd2ec3be327c636b024562db6ac5df1cffdbee74c994736fd49803234d2baffbc0054f28ba5ec76494a467b4106955bb4084af7746d269241628c667003e9d39288b190ad5cef218ada625cbba8be411bb153828d8d3634e8f586638e2448425bc5b671be69800392ccbdebc945a5099c7406f6a11824105ecad345e525957053e77fbc0119d6b3fa7f854527e816cfce0d95dac66888e07e8990c95103d8e46124aac16f152e088520d7ec8325e3a2456f840e5b77ef0e3c410b347ccaf8a87516d10b88d436563c80712153273993afc320ec49b638225f58de464a1345e62a564b398939f96f6f4b7cf21b583609f85495af1552102486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a7021024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d2102aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e2103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c2103b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a2102ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba5542102df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e89509357ae00"
|
||||
|
||||
var headerMsg HeadersMessage
|
||||
|
||||
rawBlockBytes, _ := hex.DecodeString(rawBlockHeaders)
|
||||
|
||||
r := bytes.NewReader(rawBlockBytes)
|
||||
|
||||
err := headerMsg.DecodePayload(r)
|
||||
|
||||
assert.Equal(t, 1, len(headerMsg.Headers))
|
||||
|
||||
header := headerMsg.Headers[0]
|
||||
err = header.createHash()
|
||||
|
||||
assert.Equal(t, "f3c4ec44c07eccbda974f1ee34bc6654ab6d3f22cd89c2e5c593a16d6cc7e6e8", header.Hash.ReverseString())
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
err = headerMsg.EncodePayload(buf)
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
assert.Equal(t, hex.EncodeToString(rawBlockBytes), hex.EncodeToString(buf.Bytes()))
|
||||
}
|
114
_pkg.dev/wire/payload/minventory.go
Normal file
114
_pkg.dev/wire/payload/minventory.go
Normal file
|
@ -0,0 +1,114 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
)
|
||||
|
||||
//InvType represents the enum of inventory types
|
||||
type InvType uint8
|
||||
|
||||
const (
|
||||
// InvTypeTx represents the transaction inventory type
|
||||
InvTypeTx InvType = 0x01
|
||||
// InvTypeBlock represents the block inventory type
|
||||
InvTypeBlock InvType = 0x02
|
||||
// InvTypeConsensus represents the consensus inventory type
|
||||
InvTypeConsensus InvType = 0xe0
|
||||
)
|
||||
|
||||
const maxHashes = 0x10000000
|
||||
|
||||
var errMaxHash = errors.New("max size For Hashes reached")
|
||||
|
||||
// InvMessage represents an Inventory message on the neo-network
|
||||
type InvMessage struct {
|
||||
cmd command.Type
|
||||
Type InvType
|
||||
Hashes []util.Uint256
|
||||
}
|
||||
|
||||
//NewInvMessage returns an InvMessage object
|
||||
func NewInvMessage(typ InvType) (*InvMessage, error) {
|
||||
|
||||
inv := &InvMessage{
|
||||
command.Inv,
|
||||
typ,
|
||||
nil,
|
||||
}
|
||||
return inv, nil
|
||||
}
|
||||
|
||||
func newAbstractInv(typ InvType, cmd command.Type) (*InvMessage, error) {
|
||||
inv, err := NewInvMessage(typ)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inv.cmd = cmd
|
||||
|
||||
return inv, nil
|
||||
|
||||
}
|
||||
|
||||
// AddHash adds a hash to the list of hashes
|
||||
func (inv *InvMessage) AddHash(h util.Uint256) error {
|
||||
if len(inv.Hashes)+1 > maxHashes {
|
||||
return errMaxHash
|
||||
}
|
||||
inv.Hashes = append(inv.Hashes, h)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddHashes adds multiple hashes to the list of hashes
|
||||
func (inv *InvMessage) AddHashes(hashes []util.Uint256) error {
|
||||
var err error
|
||||
for _, hash := range hashes {
|
||||
err = inv.AddHash(hash)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (inv *InvMessage) DecodePayload(r io.Reader) error {
|
||||
br := &util.BinReader{R: r}
|
||||
|
||||
br.Read(&inv.Type)
|
||||
|
||||
listLen := br.VarUint()
|
||||
inv.Hashes = make([]util.Uint256, listLen)
|
||||
|
||||
for i := 0; i < int(listLen); i++ {
|
||||
br.Read(&inv.Hashes[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (inv *InvMessage) EncodePayload(w io.Writer) error {
|
||||
|
||||
bw := &util.BinWriter{W: w}
|
||||
bw.Write(inv.Type)
|
||||
|
||||
lenhashes := len(inv.Hashes)
|
||||
bw.VarUint(uint64(lenhashes))
|
||||
|
||||
for _, hash := range inv.Hashes {
|
||||
|
||||
bw.Write(hash)
|
||||
|
||||
}
|
||||
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Command Implements messager interface
|
||||
func (inv *InvMessage) Command() command.Type {
|
||||
return inv.cmd
|
||||
}
|
78
_pkg.dev/wire/payload/minventory_test.go
Normal file
78
_pkg.dev/wire/payload/minventory_test.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewInventory(t *testing.T) {
|
||||
msgInv, err := NewInvMessage(InvTypeBlock)
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, command.Inv, msgInv.Command())
|
||||
|
||||
hash, _ := util.Uint256DecodeBytes([]byte("hello"))
|
||||
err = msgInv.AddHash(hash)
|
||||
assert.Equal(t, nil, err)
|
||||
}
|
||||
|
||||
// Adjust test time or it will timeout
|
||||
// func TestMaxHashes(t *testing.T) {
|
||||
// msgInv, err := NewInvMessage(InvTypeBlock)
|
||||
// assert.Equal(t, nil, err)
|
||||
|
||||
// hash, _ := util.Uint256DecodeBytes([]byte("hello"))
|
||||
|
||||
// for i := 0; i <= maxHashes+1; i++ {
|
||||
// err = msgInv.AddHash(hash)
|
||||
// }
|
||||
// if err == nil {
|
||||
// assert.Fail(t, "Max Hashes Exceeded, only allowed %v but have %v", maxHashes, len(msgInv.Hashes))
|
||||
// } else if err != MaxHashError {
|
||||
// assert.Fail(t, "Expected a MaxHashError, however we got %s", err.Error())
|
||||
// }
|
||||
// }
|
||||
func TestEncodeDecodePayload(t *testing.T) {
|
||||
msgInv, err := NewInvMessage(InvTypeBlock)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
blockOneHash := "d782db8a38b0eea0d7394e0f007c61c71798867578c77c387c08113903946cc9"
|
||||
hash, _ := util.Uint256DecodeString(blockOneHash)
|
||||
|
||||
err = msgInv.AddHash(hash)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err = msgInv.EncodePayload(buf)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
numOfHashes := []byte{1}
|
||||
expected := append([]byte{uint8(InvTypeBlock)}, numOfHashes...)
|
||||
expected = append(expected, hash.Bytes()...)
|
||||
|
||||
assert.Equal(t, hex.EncodeToString(expected), hex.EncodeToString(buf.Bytes()))
|
||||
|
||||
var InvDec InvMessage
|
||||
r := bytes.NewReader(buf.Bytes())
|
||||
err = InvDec.DecodePayload(r)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
assert.Equal(t, 1, len(InvDec.Hashes))
|
||||
assert.Equal(t, blockOneHash, hex.EncodeToString(InvDec.Hashes[0].Bytes()))
|
||||
|
||||
}
|
||||
func TestEmptyInv(t *testing.T) {
|
||||
msgInv, err := NewInvMessage(InvTypeBlock)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
msgInv.EncodePayload(buf)
|
||||
assert.Equal(t, []byte{byte(InvTypeBlock), 0}, buf.Bytes())
|
||||
assert.Equal(t, 0, len(msgInv.Hashes))
|
||||
}
|
30
_pkg.dev/wire/payload/mmempool.go
Normal file
30
_pkg.dev/wire/payload/mmempool.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
)
|
||||
|
||||
// GetMempool represents a GetMempool message on the neo-network
|
||||
type GetMempool struct{}
|
||||
|
||||
//NewGetMempool returns a GetMempool message
|
||||
func NewGetMempool() (*GetMempool, error) {
|
||||
return &GetMempool{}, nil
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (v *GetMempool) DecodePayload(r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (v *GetMempool) EncodePayload(w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Command Implements messager interface
|
||||
func (v *GetMempool) Command() command.Type {
|
||||
return command.Mempool
|
||||
}
|
35
_pkg.dev/wire/payload/mtx.go
Normal file
35
_pkg.dev/wire/payload/mtx.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
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
|
||||
}
|
30
_pkg.dev/wire/payload/mverack.go
Normal file
30
_pkg.dev/wire/payload/mverack.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
)
|
||||
|
||||
//VerackMessage represents a verack message on the neo-network
|
||||
type VerackMessage struct{}
|
||||
|
||||
//NewVerackMessage returns a verack message
|
||||
func NewVerackMessage() (*VerackMessage, error) {
|
||||
return &VerackMessage{}, nil
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (v *VerackMessage) DecodePayload(r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (v *VerackMessage) EncodePayload(w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Command Implements messager interface
|
||||
func (v *VerackMessage) Command() command.Type {
|
||||
return command.Verack
|
||||
}
|
17
_pkg.dev/wire/payload/mverack_test.go
Normal file
17
_pkg.dev/wire/payload/mverack_test.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewVerack(t *testing.T) {
|
||||
|
||||
verackMessage, err := NewVerackMessage()
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, command.Verack, verackMessage.Command())
|
||||
}
|
93
_pkg.dev/wire/payload/mversion.go
Normal file
93
_pkg.dev/wire/payload/mversion.go
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Copied and Modified for NEO from: https://github.com/decred/dcrd/blob/master/wire/VersionMessage.go
|
||||
|
||||
package payload
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/command"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/protocol"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
)
|
||||
|
||||
const minMsgVersionSize = 28
|
||||
|
||||
var errInvalidNetAddr = errors.New("provided net.Addr is not a net.TCPAddr")
|
||||
|
||||
//VersionMessage represents a version message on the neo-network
|
||||
type VersionMessage struct {
|
||||
Version protocol.Version
|
||||
Timestamp uint32
|
||||
Services protocol.ServiceFlag
|
||||
IP net.IP
|
||||
Port uint16
|
||||
Nonce uint32
|
||||
UserAgent []byte
|
||||
StartHeight uint32
|
||||
Relay bool
|
||||
}
|
||||
|
||||
//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) {
|
||||
|
||||
tcpAddr, ok := addr.(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, errInvalidNetAddr
|
||||
}
|
||||
|
||||
version := &VersionMessage{
|
||||
pver,
|
||||
uint32(time.Now().Unix()),
|
||||
services,
|
||||
tcpAddr.IP,
|
||||
uint16(tcpAddr.Port),
|
||||
nonce,
|
||||
[]byte(userAgent),
|
||||
startHeight,
|
||||
relay,
|
||||
}
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (v *VersionMessage) DecodePayload(r io.Reader) error {
|
||||
br := &util.BinReader{R: r}
|
||||
br.Read(&v.Version)
|
||||
br.Read(&v.Services)
|
||||
br.Read(&v.Timestamp)
|
||||
br.Read(&v.Port) // Port is not BigEndian as stated in the docs
|
||||
br.Read(&v.Nonce)
|
||||
|
||||
var lenUA uint8
|
||||
br.Read(&lenUA)
|
||||
|
||||
v.UserAgent = make([]byte, lenUA)
|
||||
br.Read(&v.UserAgent)
|
||||
br.Read(&v.StartHeight)
|
||||
br.Read(&v.Relay)
|
||||
return br.Err
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (v *VersionMessage) EncodePayload(w io.Writer) error {
|
||||
bw := &util.BinWriter{W: w}
|
||||
|
||||
bw.Write(v.Version)
|
||||
bw.Write(v.Services)
|
||||
bw.Write(v.Timestamp)
|
||||
bw.Write(v.Port) // Not big End
|
||||
bw.Write(v.Nonce)
|
||||
bw.Write(uint8(len(v.UserAgent)))
|
||||
bw.Write(v.UserAgent)
|
||||
bw.Write(v.StartHeight)
|
||||
bw.Write(v.Relay)
|
||||
return bw.Err
|
||||
}
|
||||
|
||||
// Command Implements messager interface
|
||||
func (v *VersionMessage) Command() command.Type {
|
||||
return command.Version
|
||||
}
|
59
_pkg.dev/wire/payload/mversion_test.go
Normal file
59
_pkg.dev/wire/payload/mversion_test.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/rand"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/protocol"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidNewVersionMessage(t *testing.T) {
|
||||
|
||||
expectedIP := "127.0.0.1"
|
||||
expectedPort := 8333
|
||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP(expectedIP), Port: expectedPort}
|
||||
nonce := randRange(12949672, 42949672)
|
||||
message, err := NewVersionMessage(tcpAddrMe, 0, true, protocol.DefaultVersion, protocol.UserAgent, nonce, protocol.NodePeerService)
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, expectedIP, message.IP.String())
|
||||
assert.Equal(t, uint16(expectedPort), message.Port)
|
||||
assert.Equal(t, protocol.DefaultVersion, message.Version)
|
||||
}
|
||||
func TestEncode(t *testing.T) {
|
||||
|
||||
expectedIP := "127.0.0.1"
|
||||
expectedPort := 8333
|
||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP(expectedIP), Port: expectedPort}
|
||||
nonce := randRange(12949672, 42949672)
|
||||
message, err := NewVersionMessage(tcpAddrMe, 0, true, protocol.DefaultVersion, protocol.UserAgent, nonce, protocol.NodePeerService)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err = message.EncodePayload(buf)
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, len(message.UserAgent)+minMsgVersionSize, int(buf.Len()))
|
||||
}
|
||||
func TestLenIsCorrect(t *testing.T) {
|
||||
|
||||
expectedIP := "127.0.0.1"
|
||||
expectedPort := 8333
|
||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP(expectedIP), Port: expectedPort}
|
||||
nonce := randRange(12949672, 42949672)
|
||||
message, err := NewVersionMessage(tcpAddrMe, 0, true, protocol.DefaultVersion, protocol.UserAgent, nonce, protocol.NodePeerService)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err = message.EncodePayload(buf)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
assert.Equal(t, len(message.UserAgent)+minMsgVersionSize, len(buf.Bytes()))
|
||||
}
|
||||
|
||||
func randRange(min, max int) uint32 {
|
||||
rand.Seed(time.Now().Unix() + int64(rand.Uint64()))
|
||||
return uint32(rand.Intn(max-min) + min)
|
||||
}
|
59
_pkg.dev/wire/payload/net_addr.go
Normal file
59
_pkg.dev/wire/payload/net_addr.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/protocol"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/util"
|
||||
)
|
||||
|
||||
//NetAddr is an abstraction for the IP layer
|
||||
type NetAddr struct {
|
||||
Timestamp uint32
|
||||
IP [16]byte
|
||||
Port uint16
|
||||
Service protocol.ServiceFlag
|
||||
}
|
||||
|
||||
//NewNetAddr returns a NetAddr object
|
||||
func NewNetAddr(time uint32, ip [16]byte, port uint16, service protocol.ServiceFlag) (*NetAddr, error) {
|
||||
return &NetAddr{time, ip, port, service}, nil
|
||||
}
|
||||
|
||||
//NewAddrFromVersionMessage returns a NetAddr object from a version message
|
||||
func NewAddrFromVersionMessage(version VersionMessage) (*NetAddr, error) {
|
||||
|
||||
var ip [16]byte
|
||||
|
||||
copy(ip[:], []byte(version.IP)[:16])
|
||||
|
||||
return NewNetAddr(version.Timestamp, ip, version.Port, version.Services)
|
||||
}
|
||||
|
||||
// EncodePayload Implements messager interface
|
||||
func (n *NetAddr) EncodePayload(bw *util.BinWriter) {
|
||||
|
||||
bw.Write(uint32(time.Now().Unix()))
|
||||
bw.Write(protocol.NodePeerService)
|
||||
bw.WriteBigEnd(n.IP)
|
||||
bw.WriteBigEnd(n.Port)
|
||||
}
|
||||
|
||||
// DecodePayload Implements Messager interface
|
||||
func (n *NetAddr) DecodePayload(br *util.BinReader) {
|
||||
|
||||
br.Read(&n.Timestamp)
|
||||
br.Read(&n.Service)
|
||||
br.ReadBigEnd(&n.IP)
|
||||
br.ReadBigEnd(&n.Port)
|
||||
}
|
||||
|
||||
//IPPort returns the IPPort from the NetAddr
|
||||
func (n *NetAddr) IPPort() string {
|
||||
ip := net.IP(n.IP[:]).String()
|
||||
port := strconv.Itoa(int(n.Port))
|
||||
ipport := ip + ":" + port
|
||||
return ipport
|
||||
}
|
61
_pkg.dev/wire/payload/transaction/Attribute.go
Normal file
61
_pkg.dev/wire/payload/transaction/Attribute.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
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)
|
||||
}
|
||||
}
|
32
_pkg.dev/wire/payload/transaction/Input.go
Normal file
32
_pkg.dev/wire/payload/transaction/Input.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
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)
|
||||
}
|
38
_pkg.dev/wire/payload/transaction/Output.go
Normal file
38
_pkg.dev/wire/payload/transaction/Output.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
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)
|
||||
}
|
37
_pkg.dev/wire/payload/transaction/Witness.go
Normal file
37
_pkg.dev/wire/payload/transaction/Witness.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
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
|
||||
}
|
16
_pkg.dev/wire/payload/transaction/assettype.go
Normal file
16
_pkg.dev/wire/payload/transaction/assettype.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
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
|
||||
)
|
49
_pkg.dev/wire/payload/transaction/attr_usage.go
Normal file
49
_pkg.dev/wire/payload/transaction/attr_usage.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
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
|
||||
)
|
202
_pkg.dev/wire/payload/transaction/base.go
Normal file
202
_pkg.dev/wire/payload/transaction/base.go
Normal file
|
@ -0,0 +1,202 @@
|
|||
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
|
||||
}
|
43
_pkg.dev/wire/payload/transaction/claim.go
Normal file
43
_pkg.dev/wire/payload/transaction/claim.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
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)
|
||||
}
|
||||
|
||||
}
|
38
_pkg.dev/wire/payload/transaction/claim_test.go
Normal file
38
_pkg.dev/wire/payload/transaction/claim_test.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
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()))
|
||||
}
|
28
_pkg.dev/wire/payload/transaction/contract.go
Normal file
28
_pkg.dev/wire/payload/transaction/contract.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
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) {}
|
45
_pkg.dev/wire/payload/transaction/contract_test.go
Normal file
45
_pkg.dev/wire/payload/transaction/contract_test.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction/types"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEncodeDecodeContract(t *testing.T) {
|
||||
|
||||
// mainnet transaction: bdf6cc3b9af12a7565bda80933a75ee8cef1bc771d0d58effc08e4c8b436da79
|
||||
rawtx := "80000001888da99f8f497fd65c4325786a09511159c279af4e7eb532e9edd628c87cc1ee0000019b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50082167010000000a8666b4830229d6a1a9b80f6088059191c122d2b0141409e79e132290c82916a88f1a3db5cf9f3248b780cfece938ab0f0812d0e188f3a489c7d1a23def86bd69d863ae67de753b2c2392e9497eadc8eb9fc43aa52c645232103e2f6a334e05002624cf616f01a62cff2844c34a3b08ca16048c259097e315078ac"
|
||||
rawtxBytes, _ := hex.DecodeString(rawtx)
|
||||
c := NewContract(30)
|
||||
|
||||
r := bytes.NewReader(rawtxBytes)
|
||||
err := c.Decode(r)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
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]
|
||||
|
||||
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())
|
||||
|
||||
// Encode
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
err = c.Encode(buf)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
assert.Equal(t, rawtxBytes, buf.Bytes())
|
||||
|
||||
}
|
33
_pkg.dev/wire/payload/transaction/enrollment.go
Normal file
33
_pkg.dev/wire/payload/transaction/enrollment.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
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)
|
||||
}
|
30
_pkg.dev/wire/payload/transaction/enrollment_test.go
Normal file
30
_pkg.dev/wire/payload/transaction/enrollment_test.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
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())
|
||||
}
|
61
_pkg.dev/wire/payload/transaction/invocation.go
Normal file
61
_pkg.dev/wire/payload/transaction/invocation.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
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
|
||||
}
|
78
_pkg.dev/wire/payload/transaction/invocation_test.go
Normal file
78
_pkg.dev/wire/payload/transaction/invocation_test.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
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())
|
||||
|
||||
}
|
34
_pkg.dev/wire/payload/transaction/issue.go
Normal file
34
_pkg.dev/wire/payload/transaction/issue.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
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) {}
|
8
_pkg.dev/wire/payload/transaction/issue_test.go
Normal file
8
_pkg.dev/wire/payload/transaction/issue_test.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
package transaction
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEncodeDecodeIssue(t *testing.T) {
|
||||
|
||||
// This is the same as Contract, as it has no special fields.
|
||||
}
|
32
_pkg.dev/wire/payload/transaction/miner.go
Normal file
32
_pkg.dev/wire/payload/transaction/miner.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
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)
|
||||
}
|
37
_pkg.dev/wire/payload/transaction/miner_test.go
Normal file
37
_pkg.dev/wire/payload/transaction/miner_test.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"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)
|
||||
assert.Equal(t, uint32(571397116), m.Nonce)
|
||||
|
||||
assert.Equal(t, "a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264", m.Hash.ReverseString())
|
||||
|
||||
// Encode
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
err = m.Encode(buf)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
assert.Equal(t, rawtxBytes, buf.Bytes())
|
||||
|
||||
}
|
17
_pkg.dev/wire/payload/transaction/paramtype.go
Normal file
17
_pkg.dev/wire/payload/transaction/paramtype.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
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
|
||||
)
|
38
_pkg.dev/wire/payload/transaction/publickey.go
Normal file
38
_pkg.dev/wire/payload/transaction/publickey.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
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...)
|
||||
}
|
90
_pkg.dev/wire/payload/transaction/publish.go
Normal file
90
_pkg.dev/wire/payload/transaction/publish.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
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()
|
||||
}
|
33
_pkg.dev/wire/payload/transaction/publish_test.go
Normal file
33
_pkg.dev/wire/payload/transaction/publish_test.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
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())
|
||||
|
||||
}
|
58
_pkg.dev/wire/payload/transaction/register.go
Normal file
58
_pkg.dev/wire/payload/transaction/register.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
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)
|
||||
}
|
54
_pkg.dev/wire/payload/transaction/register_test.go
Normal file
54
_pkg.dev/wire/payload/transaction/register_test.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
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())
|
||||
}
|
43
_pkg.dev/wire/payload/transaction/state.go
Normal file
43
_pkg.dev/wire/payload/transaction/state.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
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)
|
||||
}
|
||||
}
|
47
_pkg.dev/wire/payload/transaction/state_test.go
Normal file
47
_pkg.dev/wire/payload/transaction/state_test.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"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)
|
||||
|
||||
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, "a192cbabc6d613ecfcce43fd09e9197556ca5cf7d4bd1f6c65726ea9f08441cb", input.PrevHash.ReverseString())
|
||||
assert.Equal(t, uint16(0), input.PrevIndex)
|
||||
|
||||
assert.Equal(t, 1, len(s.Descriptors))
|
||||
descriptor := s.Descriptors[0]
|
||||
assert.Equal(t, "03c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c1", hex.EncodeToString(descriptor.Key))
|
||||
assert.Equal(t, "52656769737465726564", hex.EncodeToString(descriptor.Value))
|
||||
assert.Equal(t, "\x01", descriptor.Field)
|
||||
assert.Equal(t, Validator, descriptor.Type)
|
||||
|
||||
// Encode
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
err = s.Encode(buf)
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, rawtxBytes, buf.Bytes())
|
||||
assert.Equal(t, "8abf5ebdb9a8223b12109513647f45bd3c0a6cf1a6346d56684cff71ba308724", s.Hash.ReverseString())
|
||||
}
|
55
_pkg.dev/wire/payload/transaction/statedescriptor.go
Normal file
55
_pkg.dev/wire/payload/transaction/statedescriptor.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
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)
|
||||
}
|
63
_pkg.dev/wire/payload/transaction/types/types.go
Normal file
63
_pkg.dev/wire/payload/transaction/types/types.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
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"
|
||||
}
|
||||
}
|
62
_pkg.dev/wire/payload/transaction/util.go
Normal file
62
_pkg.dev/wire/payload/transaction/util.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
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
|
||||
}
|
24
_pkg.dev/wire/payload/transaction/version/version.go
Normal file
24
_pkg.dev/wire/payload/transaction/version/version.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
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)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue