Skip to content
Snippets Groups Projects
Unverified Commit 654f63ca authored by lunfardo314's avatar lunfardo314 Committed by GitHub
Browse files

Merge pull request #14 from iotaledger/develop

Develop
parents 79ba3960 2771257e
No related branches found
No related tags found
No related merge requests found
Showing
with 577 additions and 151 deletions
name: Test GoShimmer
on:
push:
pull_request:
types: [opened, reopened]
jobs:
integration-test:
name: Integration Tests
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Build GoShimmer Docker network
run: docker-compose -f tools/integration-tests/docker-compose.yml up -d --scale peer_replica=5 --build
- name: Dispay containers
run: docker ps -a
- name: Run integration tests
run: docker-compose -f tools/integration-tests/tester/docker-compose.yml up --abort-on-container-exit --exit-code-from tester --build
- name: Stop GoShimmer Docker network
if: always()
run: docker-compose -f tools/integration-tests/docker-compose.yml stop
- name: Create logs from containers in network
if: always()
run: |
docker logs entry_node > tools/integration-tests/logs/entry_node.log
docker logs peer_master > tools/integration-tests/logs/peer_master.log
docker logs integration-tests_peer_replica_1 > tools/integration-tests/logs/peer_replica_1.log
docker logs integration-tests_peer_replica_2 > tools/integration-tests/logs/peer_replica_2.log
docker logs integration-tests_peer_replica_3 > tools/integration-tests/logs/peer_replica_3.log
docker logs integration-tests_peer_replica_4 > tools/integration-tests/logs/peer_replica_4.log
docker logs integration-tests_peer_replica_5 > tools/integration-tests/logs/peer_replica_5.log
docker logs tester > tools/integration-tests/logs/tester.log
- name: Save logs as artifacts
if: always()
uses: actions/upload-artifact@v1
with:
name: container-logs
path: tools/integration-tests/logs
- name: Clean up
if: always()
run: docker-compose -f tools/integration-tests/docker-compose.yml down
......@@ -6,7 +6,7 @@ on:
jobs:
build:
name: Test GoShimmer
name: Unit tests
runs-on: ubuntu-latest
steps:
......@@ -19,4 +19,4 @@ jobs:
uses: actions/checkout@v2
- name: Run Tests
run: go test ./...
run: go test $(go list ./... | grep -v drng)
......@@ -34,8 +34,6 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
# user:group is nonroot:nonroot, uid:gid = 65532:65532
FROM gcr.io/distroless/static@sha256:23aa732bba4c8618c0d97c26a72a32997363d591807b0d4c31b0bbc8a774bddf
VOLUME /mainnetdb
EXPOSE 14666/tcp
EXPOSE 14626/udp
......@@ -44,4 +42,4 @@ COPY --from=build /go/bin/goshimmer /run/goshimmer
# Copy the default config
COPY config.default.json /config.json
ENTRYPOINT ["/run/goshimmer", "--config-dir=/", "--database.directory=/mainnetdb"]
ENTRYPOINT ["/run/goshimmer", "--config-dir=/", "--database.directory=/tmp/mainnetdb"]
package client
import (
"fmt"
"net/http"
webapi_autopeering "github.com/iotaledger/goshimmer/plugins/webapi/autopeering"
)
const (
routeGetNeighbors = "autopeering/neighbors"
)
// GetNeighbors gets the chosen/accepted neighbors.
// If knownPeers is set, also all known peers to the node are returned additionally.
func (api *GoShimmerAPI) GetNeighbors(knownPeers bool) (*webapi_autopeering.Response, error) {
res := &webapi_autopeering.Response{}
if err := api.do(http.MethodGet, func() string {
if !knownPeers {
return routeGetNeighbors
}
return fmt.Sprintf("%s?known=1", routeGetNeighbors)
}(), nil, res); err != nil {
return nil, err
}
return res, nil
}
package client
import (
"net/http"
webapi_data "github.com/iotaledger/goshimmer/plugins/webapi/data"
)
const (
routeData = "data"
)
// Data sends the given data (payload) by creating a message in the backend.
func (api *GoShimmerAPI) Data(data []byte) (string, error) {
res := &webapi_data.Response{}
if err := api.do(http.MethodPost, routeData,
&webapi_data.Request{Data: data}, res); err != nil {
return "", err
}
return res.Id, nil
}
package client
import (
"net/http"
webapi_collectiveBeacon "github.com/iotaledger/goshimmer/plugins/webapi/drng/collectiveBeacon"
webapi_committee "github.com/iotaledger/goshimmer/plugins/webapi/drng/info/committee"
webapi_randomness "github.com/iotaledger/goshimmer/plugins/webapi/drng/info/randomness"
)
const (
routeCollectiveBeacon = "drng/collectiveBeacon"
routeRandomness = "drng/info/randomness"
routeCommittee = "drng/info/committee"
)
// BroadcastCollectiveBeacon sends the given collective beacon (payload) by creating a message in the backend.
func (api *GoShimmerAPI) BroadcastCollectiveBeacon(payload []byte) (string, error) {
res := &webapi_collectiveBeacon.Response{}
if err := api.do(http.MethodPost, routeCollectiveBeacon,
&webapi_collectiveBeacon.Request{Payload: payload}, res); err != nil {
return "", err
}
return res.Id, nil
}
// GetRandomness gets the current randomness.
func (api *GoShimmerAPI) GetRandomness() (*webapi_randomness.Response, error) {
res := &webapi_randomness.Response{}
if err := api.do(http.MethodGet, func() string {
return routeRandomness
}(), nil, res); err != nil {
return nil, err
}
return res, nil
}
// GetCommittee gets the current committee.
func (api *GoShimmerAPI) GetCommittee() (*webapi_committee.Response, error) {
res := &webapi_committee.Response{}
if err := api.do(http.MethodGet, func() string {
return routeCommittee
}(), nil, res); err != nil {
return nil, err
}
return res, nil
}
// Implements a very simple wrapper for GoShimmer's web API .
package goshimmer
package client
import (
"bytes"
......@@ -9,18 +9,6 @@ import (
"io"
"io/ioutil"
"net/http"
webapi_broadcastData "github.com/iotaledger/goshimmer/plugins/webapi/broadcastData"
webapi_findTransactionHashes "github.com/iotaledger/goshimmer/plugins/webapi/findTransactionHashes"
webapi_getNeighbors "github.com/iotaledger/goshimmer/plugins/webapi/getNeighbors"
webapi_getTransactionObjectsByHash "github.com/iotaledger/goshimmer/plugins/webapi/getTransactionObjectsByHash"
webapi_getTransactionTrytesByHash "github.com/iotaledger/goshimmer/plugins/webapi/getTransactionTrytesByHash"
webapi_gtta "github.com/iotaledger/goshimmer/plugins/webapi/gtta"
webapi_spammer "github.com/iotaledger/goshimmer/plugins/webapi/spammer"
webapi_auth "github.com/iotaledger/goshimmer/plugins/webauth"
"github.com/iotaledger/iota.go/consts"
"github.com/iotaledger/iota.go/guards"
"github.com/iotaledger/iota.go/trinary"
)
var (
......@@ -33,29 +21,20 @@ var (
)
const (
routeBroadcastData = "broadcastData"
routeGetTransactionTrytesByHash = "getTransactionTrytesByHash"
routeGetTransactionObjectsByHash = "getTransactionObjectsByHash"
routeFindTransactionsHashes = "findTransactionHashes"
routeGetNeighbors = "getNeighbors"
routeGetTransactionsToApprove = "getTransactionsToApprove"
routeSpammer = "spammer"
routeLogin = "login"
contentTypeJSON = "application/json"
)
func NewGoShimmerAPI(node string, httpClient ...http.Client) *GoShimmerAPI {
func NewGoShimmerAPI(baseUrl string, httpClient ...http.Client) *GoShimmerAPI {
if len(httpClient) > 0 {
return &GoShimmerAPI{node: node, httpClient: httpClient[0]}
return &GoShimmerAPI{baseUrl: baseUrl, httpClient: httpClient[0]}
}
return &GoShimmerAPI{node: node}
return &GoShimmerAPI{baseUrl: baseUrl}
}
// GoShimmerAPI is an API wrapper over the web API of GoShimmer.
type GoShimmerAPI struct {
httpClient http.Client
node string
baseUrl string
jwt string
}
......@@ -83,7 +62,7 @@ func interpretBody(res *http.Response, decodeTo interface{}) error {
case http.StatusInternalServerError:
return fmt.Errorf("%w: %s", ErrInternalServerError, errRes.Error)
case http.StatusNotFound:
return fmt.Errorf("%w: %s", ErrNotFound, errRes.Error)
return fmt.Errorf("%w: %s", ErrNotFound, res.Request.URL.String())
case http.StatusBadRequest:
return fmt.Errorf("%w: %s", ErrBadRequest, errRes.Error)
case http.StatusUnauthorized:
......@@ -107,7 +86,7 @@ func (api *GoShimmerAPI) do(method string, route string, reqObj interface{}, res
}
// construct request
req, err := http.NewRequest(method, fmt.Sprintf("%s/%s", api.node, route), func() io.Reader {
req, err := http.NewRequest(method, fmt.Sprintf("%s/%s", api.baseUrl, route), func() io.Reader {
if data == nil {
return nil
}
......@@ -143,117 +122,6 @@ func (api *GoShimmerAPI) do(method string, route string, reqObj interface{}, res
return nil
}
// Login authorizes this API instance against the web API.
// You must call this function before any before any other call, if the web-auth plugin is enabled.
func (api *GoShimmerAPI) Login(username string, password string) error {
res := &webapi_auth.Response{}
if err := api.do(http.MethodPost, routeLogin,
&webapi_auth.Request{Username: username, Password: password}, res); err != nil {
return err
}
api.jwt = res.Token
return nil
}
// BroadcastData sends the given data by creating a zero value transaction in the backend targeting the given address.
func (api *GoShimmerAPI) BroadcastData(targetAddress trinary.Trytes, data string) (trinary.Hash, error) {
if !guards.IsHash(targetAddress) {
return "", fmt.Errorf("%w: invalid address: %s", consts.ErrInvalidHash, targetAddress)
}
res := &webapi_broadcastData.Response{}
if err := api.do(http.MethodPost, routeBroadcastData,
&webapi_broadcastData.Request{Address: targetAddress, Data: data}, res); err != nil {
return "", err
}
return res.Hash, nil
}
// GetTransactionTrytesByHash gets the corresponding transaction trytes given the transaction hashes.
func (api *GoShimmerAPI) GetTransactionTrytesByHash(txHashes trinary.Hashes) ([]trinary.Trytes, error) {
for _, hash := range txHashes {
if !guards.IsTrytes(hash) {
return nil, fmt.Errorf("%w: invalid hash: %s", consts.ErrInvalidHash, hash)
}
}
res := &webapi_getTransactionTrytesByHash.Response{}
if err := api.do(http.MethodPost, routeGetTransactionTrytesByHash,
&webapi_getTransactionTrytesByHash.Request{Hashes: txHashes}, res); err != nil {
return nil, err
}
return res.Trytes, nil
}
// GetTransactionObjectsByHash gets the transaction objects given the transaction hashes.
func (api *GoShimmerAPI) GetTransactionObjectsByHash(txHashes trinary.Hashes) ([]webapi_getTransactionObjectsByHash.Transaction, error) {
for _, hash := range txHashes {
if !guards.IsTrytes(hash) {
return nil, fmt.Errorf("%w: invalid hash: %s", consts.ErrInvalidHash, hash)
}
}
res := &webapi_getTransactionObjectsByHash.Response{}
if err := api.do(http.MethodPost, routeGetTransactionObjectsByHash,
&webapi_getTransactionObjectsByHash.Request{Hashes: txHashes}, res); err != nil {
return nil, err
}
return res.Transactions, nil
}
// FindTransactionHashes finds the given transaction hashes given the query.
func (api *GoShimmerAPI) FindTransactionHashes(query *webapi_findTransactionHashes.Request) ([]trinary.Hashes, error) {
for _, hash := range query.Addresses {
if !guards.IsTrytes(hash) {
return nil, fmt.Errorf("%w: invalid hash: %s", consts.ErrInvalidHash, hash)
}
}
res := &webapi_findTransactionHashes.Response{}
if err := api.do(http.MethodPost, routeFindTransactionsHashes, query, res); err != nil {
return nil, err
}
return res.Transactions, nil
}
// GetNeighbors gets the chosen/accepted neighbors.
// If knownPeers is set, also all known peers to the node are returned additionally.
func (api *GoShimmerAPI) GetNeighbors(knownPeers bool) (*webapi_getNeighbors.Response, error) {
res := &webapi_getNeighbors.Response{}
if err := api.do(http.MethodGet, func() string {
if !knownPeers {
return routeGetNeighbors
}
return fmt.Sprintf("%s?known=1", routeGetNeighbors)
}(), nil, res); err != nil {
return nil, err
}
return res, nil
}
// GetTips executes the tip-selection on the node to retrieve tips to approve.
func (api *GoShimmerAPI) GetTransactionsToApprove() (*webapi_gtta.Response, error) {
res := &webapi_gtta.Response{}
if err := api.do(http.MethodGet, routeGetTransactionsToApprove, nil, res); err != nil {
return nil, err
}
return res, nil
}
// ToggleSpammer toggles the node internal spammer.
func (api *GoShimmerAPI) ToggleSpammer(enable bool) (*webapi_spammer.Response, error) {
res := &webapi_spammer.Response{}
if err := api.do(http.MethodGet, func() string {
if enable {
return fmt.Sprintf("%s?cmd=start", routeSpammer)
}
return fmt.Sprintf("%s?cmd=stop", routeSpammer)
}(), nil, res); err != nil {
return nil, err
}
return res, nil
func (api *GoShimmerAPI) BaseUrl() string {
return api.baseUrl
}
package client
import (
"net/http"
webapi_auth "github.com/iotaledger/goshimmer/plugins/webauth"
)
const (
routeLogin = "login"
)
// Login authorizes this API instance against the web API.
// You must call this function before any before any other call, if the web-auth plugin is enabled.
func (api *GoShimmerAPI) Login(username string, password string) error {
res := &webapi_auth.Response{}
if err := api.do(http.MethodPost, routeLogin,
&webapi_auth.Request{Username: username, Password: password}, res); err != nil {
return err
}
api.jwt = res.Token
return nil
}
package client
import (
"net/http"
webapi_message "github.com/iotaledger/goshimmer/plugins/webapi/message"
)
const (
routeFindById = "message/findById"
)
// FindMessageById finds messages by the given ids. The messages are returned in the same order as
// the given ids. Non available messages are empty at their corresponding index.
func (api *GoShimmerAPI) FindMessageById(base58EncodedIds []string) (*webapi_message.Response, error) {
res := &webapi_message.Response{}
if err := api.do(
http.MethodPost,
routeFindById,
&webapi_message.Request{Ids: base58EncodedIds},
res,
); err != nil {
return nil, err
}
return res, nil
}
package client
import (
"fmt"
"net/http"
webapi_spammer "github.com/iotaledger/goshimmer/plugins/webapi/spammer"
)
const (
routeSpammer = "spammer"
)
// ToggleSpammer toggles the node internal spammer.
func (api *GoShimmerAPI) ToggleSpammer(enable bool) (*webapi_spammer.Response, error) {
res := &webapi_spammer.Response{}
if err := api.do(http.MethodGet, func() string {
if enable {
return fmt.Sprintf("%s?cmd=start", routeSpammer)
}
return fmt.Sprintf("%s?cmd=stop", routeSpammer)
}(), nil, res); err != nil {
return nil, err
}
return res, nil
}
......@@ -28,6 +28,12 @@
"database": {
"directory": "mainnetdb"
},
"drng": {
"instanceId": 1,
"threshold": 3,
"distributedPubKey": "",
"committeeMembers": []
},
"gossip": {
"port": 14666
},
......
......@@ -14,7 +14,7 @@ services:
# make sure to give read/write access to the folder ./mainnetdb (e.g., chmod -R 777 ./mainnetdb)
# optionally, you can mount a config.json into the container
volumes:
- ./mainnetdb/:/mainnetdb/:rw
- ./mainnetdb/:/tmp/mainnetdb/:rw
#- ./config.json:/config.json:ro
# Expose ports:
# gossip: - "14666:14666/tcp"
......
......@@ -3,17 +3,19 @@ module github.com/iotaledger/goshimmer
go 1.14
require (
github.com/coreos/bbolt v1.3.3 // indirect
github.com/dgraph-io/badger/v2 v2.0.2
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/drand/drand v0.5.4
github.com/gobuffalo/packr/v2 v2.7.1
github.com/golang/protobuf v1.3.4
github.com/googollee/go-engine.io v1.4.3-0.20190924125625-798118fc0dd2
github.com/googollee/go-socket.io v1.4.3-0.20191204093753-683f8725b6d0
github.com/gorilla/websocket v1.4.1
github.com/iotaledger/hive.go v0.0.0-20200328153852-4d06dcf6bf29
github.com/iotaledger/hive.go v0.0.0-20200403132600-4c10556e08a0
github.com/iotaledger/iota.go v1.0.0-beta.14
github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/gommon v0.3.0 // indirect
github.com/labstack/gommon v0.3.0
github.com/magiconair/properties v1.8.1
github.com/mr-tron/base58 v1.1.3
github.com/panjf2000/ants/v2 v2.2.2
......@@ -28,5 +30,6 @@ require (
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
golang.org/x/net v0.0.0-20200301022130-244492dfa37a
golang.org/x/tools v0.0.0-20200330040139-fa3cc9eebcfe // indirect
google.golang.org/grpc v1.28.1
gopkg.in/src-d/go-git.v4 v4.13.1
)
This diff is collapsed.
images/integration-testing-setup.png

51.7 KiB

package drng
import (
"errors"
"time"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon/events"
cb "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon/payload"
"github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/iotaledger/hive.go/marshalutil"
)
// Dispatch parses a DRNG message and process it based on its subtype
func (drng *DRNG) Dispatch(issuer ed25519.PublicKey, timestamp time.Time, payload *payload.Payload) error {
switch payload.Header.PayloadType {
case header.TypeCollectiveBeacon:
// parse as CollectiveBeaconType
marshalUtil := marshalutil.New(payload.Bytes())
parsedPayload, err := cb.Parse(marshalUtil)
if err != nil {
return err
}
// trigger CollectiveBeaconEvent
cbEvent := &events.CollectiveBeaconEvent{
IssuerPublicKey: issuer,
Timestamp: timestamp,
InstanceID: parsedPayload.Header.InstanceID,
Round: parsedPayload.Round,
PrevSignature: parsedPayload.PrevSignature,
Signature: parsedPayload.Signature,
Dpk: parsedPayload.Dpk,
}
drng.Events.CollectiveBeacon.Trigger(cbEvent)
// process collectiveBeacon
if err := collectiveBeacon.ProcessBeacon(drng.State, cbEvent); err != nil {
return err
}
// trigger RandomnessEvent
drng.Events.Randomness.Trigger(drng.State.Randomness())
return nil
default:
return errors.New("subtype not implemented")
}
}
package drng
import (
"encoding/hex"
"testing"
"time"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload"
"github.com/iotaledger/goshimmer/packages/binary/drng/payload/header"
"github.com/iotaledger/goshimmer/packages/binary/drng/state"
"github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon"
cbPayload "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon/payload"
"github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/iotaledger/hive.go/marshalutil"
"github.com/stretchr/testify/require"
)
var (
prevSignatureTest []byte
signatureTest []byte
dpkTest []byte
issuerPK ed25519.PublicKey
committeeTest *state.Committee
timestampTest time.Time
randomnessTest *state.Randomness
)
func init() {
prevSignatureTest, _ = hex.DecodeString("ae9ba6d1445bffea8e66cb7d28fe5924e0a8d31b11b62a8710204e56e1ba84bc3694a3033e5793fcee6e75e956e5da3016cd0e22aa46fa419cd06343a7ff9d1e9c5c08f660f0bdec099e97ef99f470bb8c607ce9667a165e9caa474710f62ffd")
signatureTest, _ = hex.DecodeString("8dee56fae60dcad960f7176d0813d5415b930cf6e20c299ec2c2dfc5f2ad4903916fd462ba1abf5c32a5bfd94dcc8eba062d011a548d99df7fa1e3bbbc9a0455663d60f6ccc736c1d5b6de727dbe4427e21fb660925518be386265913f447c94")
dpkTest, _ = hex.DecodeString("a02fcd15edd52c8e134027491a43b597505b466d1679e88f70f927e57c45a93ae0765ff02fc2d015e3a02fd8748e2103")
timestampTest = time.Now()
rand, _ := collectiveBeacon.ExtractRandomness(signatureTest)
randomnessTest = &state.Randomness{
Round: 1,
Randomness: rand,
Timestamp: timestampTest,
}
kp := ed25519.GenerateKeyPair()
issuerPK = kp.PublicKey
committeeTest = &state.Committee{
InstanceID: 1,
Threshold: 3,
Identities: []ed25519.PublicKey{issuerPK},
DistributedPK: dpkTest,
}
}
func dummyPayload() *cbPayload.Payload {
header := header.New(header.TypeCollectiveBeacon, 1)
return cbPayload.New(header.InstanceID,
1,
prevSignatureTest,
signatureTest,
dpkTest)
}
func TestDispatcher(t *testing.T) {
marshalUtil := marshalutil.New(dummyPayload().Bytes())
parsedPayload, err := payload.Parse(marshalUtil)
require.NoError(t, err)
drng := New(state.SetCommittee(committeeTest))
err = drng.Dispatch(issuerPK, timestampTest, parsedPayload)
require.NoError(t, err)
require.Equal(t, *randomnessTest, drng.State.Randomness())
}
package drng
import (
"github.com/iotaledger/goshimmer/packages/binary/drng/state"
cbEvents "github.com/iotaledger/goshimmer/packages/binary/drng/subtypes/collectiveBeacon/events"
"github.com/iotaledger/hive.go/events"
)
// DRNG holds the state and events of a drng instance.
type DRNG struct {
State *state.State // The state of the DRNG.
Events *Event // The events fired on the DRNG.
}
// New creates a new DRNG instance.
func New(setters ...state.Option) *DRNG {
return &DRNG{
State: state.New(setters...),
Events: &Event{
CollectiveBeacon: events.NewEvent(cbEvents.CollectiveBeaconReceived),
Randomness: events.NewEvent(randomnessReceived),
},
}
}
package drng
import (
"github.com/iotaledger/goshimmer/packages/binary/drng/state"
"github.com/iotaledger/hive.go/events"
)
// Event holds the different events triggered by a DRNG instance.
type Event struct {
// Collective Beacon is triggered each time we receive a new CollectiveBeacon message.
CollectiveBeacon *events.Event
// Randomness is triggered each time we receive a new and valid CollectiveBeacon message.
Randomness *events.Event
}
func randomnessReceived(handler interface{}, params ...interface{}) {
handler.(func(state.Randomness))(params[0].(state.Randomness))
}
package header
import (
"github.com/iotaledger/hive.go/marshalutil"
)
// Type defines the data model of a DRNG payload type
type Type = byte
const (
// TypeCollectiveBeacon defines a CollectiveBeacon payload type
TypeCollectiveBeacon Type = 1
)
// Length defines the length of a DRNG header
const Length = 5
// Header defines defines a DRNG payload header
type Header struct {
PayloadType Type // message type
InstanceID uint32 // identifier of the DRNG instance
}
// New creates a new DRNG payload header for the given type and instance id.
func New(payloadType Type, instanceID uint32) Header {
return Header{
PayloadType: payloadType,
InstanceID: instanceID,
}
}
// Parse is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
func Parse(marshalUtil *marshalutil.MarshalUtil) (Header, error) {
header, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return FromBytes(data) })
if err != nil {
return Header{}, err
}
return header.(Header), nil
}
// FromBytes unmarshals a header from a sequence of bytes.
// It either creates a new header or fills the optionally provided object with the parsed information.
func FromBytes(bytes []byte, optionalTargetObject ...*Header) (result Header, err error, consumedBytes int) {
// determine the target object that will hold the unmarshaled information
var targetObject *Header
switch len(optionalTargetObject) {
case 0:
targetObject = &result
case 1:
targetObject = optionalTargetObject[0]
default:
panic("too many arguments in call to FromBytes")
}
// initialize helper
marshalUtil := marshalutil.New(bytes)
// read payload type from bytes
if targetObject.PayloadType, err = marshalUtil.ReadByte(); err != nil {
return
}
// read instance ID from bytes
if targetObject.InstanceID, err = marshalUtil.ReadUint32(); err != nil {
return
}
// copy result if we have provided a target object
result = *targetObject
// return the number of bytes we processed
consumedBytes = marshalUtil.ReadOffset()
return
}
// Bytes returns the header in serialized bytes form.
func (header *Header) Bytes() (bytes []byte) {
// initialize helper
marshalUtil := marshalutil.New()
// marshal the payload specific information
marshalUtil.WriteByte(header.PayloadType)
marshalUtil.WriteUint32(header.InstanceID)
bytes = marshalUtil.Bytes()
return
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment