From 82d4b6bb76f693fd070ae4061a0314d2f98de7ec Mon Sep 17 00:00:00 2001
From: Jonas Theis <mail@jonastheis.de>
Date: Mon, 20 Jul 2020 12:06:07 +0200
Subject: [PATCH] Enforce max message size/max payload size in message factory
 (#647)

* Add check for allowed payload size to message factory

* Fix factory usage in tests

* Add test

* Remove invalid payload size checks

* Adjust maxPacketSize in gossip and buffconn to 65KB

* Bones

* Upgrade to latest hive.go version

* Bones for the good boy!
---
 .../packages/tangle/signature_filter_test.go  | 13 +++++--
 .../packages/transaction/transaction.go       | 10 ------
 .../packages/transaction/transaction_test.go  | 21 ++---------
 go.mod                                        |  2 +-
 go.sum                                        |  4 +--
 .../collectiveBeacon/payload/payload.go       | 14 +-------
 .../messagefactory/messagefactory.go          | 35 ++++++++++++-------
 .../messagefactory/messagefactory_test.go     | 34 ++++++++++++++++--
 packages/binary/messagelayer/payload/data.go  |  3 --
 .../binary/messagelayer/payload/payload.go    | 22 +++++++-----
 .../messagelayer/test/data_payload_test.go    |  9 +++--
 .../binary/messagelayer/test/message_test.go  |  4 ++-
 packages/gossip/manager.go                    |  3 +-
 packages/gossip/neighbor.go                   |  2 +-
 plugins/dashboard/faucet_routes.go            |  6 ++--
 plugins/issuer/plugin.go                      |  8 ++++-
 plugins/webapi/data/plugin.go                 |  7 ----
 plugins/webapi/faucet/plugin.go               |  7 ++--
 .../builder/docker-compose.builder.yml        |  1 +
 tools/docker-network/run.sh                   |  9 ++++-
 tools/integration-tests/tester/go.mod         |  2 +-
 tools/integration-tests/tester/go.sum         |  4 +--
 22 files changed, 124 insertions(+), 96 deletions(-)

diff --git a/dapps/valuetransfers/packages/tangle/signature_filter_test.go b/dapps/valuetransfers/packages/tangle/signature_filter_test.go
index 4002da4a..7f511ac3 100644
--- a/dapps/valuetransfers/packages/tangle/signature_filter_test.go
+++ b/dapps/valuetransfers/packages/tangle/signature_filter_test.go
@@ -46,7 +46,9 @@ func TestSignatureFilter(t *testing.T) {
 		)
 
 		// parse message bytes
-		accepted, _, _, err := messageParser.Parse(messageFactory.IssuePayload(valuePayload.New(valuePayload.GenesisID, valuePayload.GenesisID, tx)).Bytes(), &peer.Peer{})
+		msg, err := messageFactory.IssuePayload(valuePayload.New(valuePayload.GenesisID, valuePayload.GenesisID, tx))
+		require.NoError(t, err)
+		accepted, _, _, err := messageParser.Parse(msg.Bytes(), &peer.Peer{})
 
 		// check results (should be rejected)
 		require.Equal(t, false, accepted)
@@ -70,7 +72,10 @@ func TestSignatureFilter(t *testing.T) {
 		tx.Sign(signaturescheme.ED25519(*seed.KeyPair(0)))
 
 		// parse message bytes
-		accepted, _, _, err := messageParser.Parse(messageFactory.IssuePayload(valuePayload.New(valuePayload.GenesisID, valuePayload.GenesisID, tx)).Bytes(), &peer.Peer{})
+		msg, err := messageFactory.IssuePayload(valuePayload.New(valuePayload.GenesisID, valuePayload.GenesisID, tx))
+		require.NoError(t, err)
+
+		accepted, _, _, err := messageParser.Parse(msg.Bytes(), &peer.Peer{})
 
 		// check results (should be accepted)
 		require.Equal(t, true, accepted)
@@ -91,7 +96,9 @@ func TestSignatureFilter(t *testing.T) {
 		require.NoError(t, err)
 
 		// parse message bytes
-		accepted, _, _, err := messageParser.Parse(messageFactory.IssuePayload(dataPayload).Bytes(), &peer.Peer{})
+		msg, err := messageFactory.IssuePayload(dataPayload)
+		require.NoError(t, err)
+		accepted, _, _, err := messageParser.Parse(msg.Bytes(), &peer.Peer{})
 
 		// check results (should be rejected)
 		require.Equal(t, false, accepted)
diff --git a/dapps/valuetransfers/packages/transaction/transaction.go b/dapps/valuetransfers/packages/transaction/transaction.go
index 928827a1..7046fe4a 100644
--- a/dapps/valuetransfers/packages/transaction/transaction.go
+++ b/dapps/valuetransfers/packages/transaction/transaction.go
@@ -317,17 +317,11 @@ func (transaction *Transaction) String() string {
 	)
 }
 
-// MaxDataPayloadSize defines the maximum size (in bytes) of the data payload.
-const MaxDataPayloadSize = 64 * 1024
-
 // SetDataPayload sets yhe dataPayload and its type
 func (transaction *Transaction) SetDataPayload(data []byte) error {
 	transaction.dataPayloadMutex.Lock()
 	defer transaction.dataPayloadMutex.Unlock()
 
-	if len(data) > MaxDataPayloadSize {
-		return fmt.Errorf("%w: %d", ErrMaxDataPayloadSizeExceeded, MaxDataPayloadSize)
-	}
 	transaction.dataPayload = data
 	return nil
 }
@@ -396,10 +390,6 @@ func (transaction *Transaction) UnmarshalObjectStorageValue(bytes []byte) (consu
 	if err != nil {
 		return
 	}
-	if dataPayloadSize > MaxDataPayloadSize {
-		err = fmt.Errorf("%w: %d", ErrMaxDataPayloadSizeExceeded, MaxDataPayloadSize)
-		return
-	}
 
 	// unmarshal data payload
 	transaction.dataPayload, err = marshalUtil.ReadBytes(int(dataPayloadSize))
diff --git a/dapps/valuetransfers/packages/transaction/transaction_test.go b/dapps/valuetransfers/packages/transaction/transaction_test.go
index 164beb5e..d1bb1727 100644
--- a/dapps/valuetransfers/packages/transaction/transaction_test.go
+++ b/dapps/valuetransfers/packages/transaction/transaction_test.go
@@ -2,7 +2,6 @@ package transaction
 
 import (
 	"bytes"
-	"strings"
 	"testing"
 
 	"github.com/iotaledger/hive.go/crypto/ed25519"
@@ -75,20 +74,6 @@ func TestShortDataPayload(t *testing.T) {
 	assert.Equal(t, false, check)
 }
 
-func TestTooLongDataPayload(t *testing.T) {
-	sigScheme := signaturescheme.ED25519(ed25519.GenerateKeyPair())
-	addr := sigScheme.Address()
-	o1 := NewOutputID(addr, RandomID())
-	inputs := NewInputs(o1)
-	bal := balance.New(balance.ColorIOTA, 1)
-	outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
-	tx := New(inputs, outputs)
-
-	dataPayload := []byte(strings.Repeat("1", MaxDataPayloadSize+1))
-	err := tx.SetDataPayload(dataPayload)
-	assert.Error(t, err)
-}
-
 func TestMarshalingEmptyDataPayload(t *testing.T) {
 	sigScheme := signaturescheme.RandBLS()
 	addr := sigScheme.Address()
@@ -206,10 +191,10 @@ func TestPutSignatureInvalid(t *testing.T) {
 }
 
 func TestInputCounts(t *testing.T) {
-	tx1 := createTransaction(MaxTransactionInputCount + 1, 1)
+	tx1 := createTransaction(MaxTransactionInputCount+1, 1)
 	assert.False(t, tx1.InputsCountValid())
 
-	tx2 := createTransaction(MaxTransactionInputCount - 1, 1)
+	tx2 := createTransaction(MaxTransactionInputCount-1, 1)
 	assert.True(t, tx2.InputsCountValid())
 }
 
@@ -228,4 +213,4 @@ func createTransaction(inputCount int, outputCount int) *Transaction {
 	outputs := NewOutputs(outputMap)
 
 	return New(inputs, outputs)
-}
\ No newline at end of file
+}
diff --git a/go.mod b/go.mod
index 7b0b7242..45c1d910 100644
--- a/go.mod
+++ b/go.mod
@@ -13,7 +13,7 @@ require (
 	github.com/gobuffalo/packr/v2 v2.8.0
 	github.com/golang/protobuf v1.4.2
 	github.com/gorilla/websocket v1.4.2
-	github.com/iotaledger/hive.go v0.0.0-20200713104016-55eaecb9d028
+	github.com/iotaledger/hive.go v0.0.0-20200720084404-e6c3b4717f40
 	github.com/labstack/echo v3.3.10+incompatible
 	github.com/labstack/gommon v0.3.0
 	github.com/magiconair/properties v1.8.1
diff --git a/go.sum b/go.sum
index 31be3a85..c425a135 100644
--- a/go.sum
+++ b/go.sum
@@ -229,8 +229,8 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/iotaledger/hive.go v0.0.0-20200713104016-55eaecb9d028 h1:GUKeANC04c4NE94Gs6rkbWfo9bfOkqtLwbnCGFLL+TY=
-github.com/iotaledger/hive.go v0.0.0-20200713104016-55eaecb9d028/go.mod h1:42UvBc41QBsuM7z1P1fABMonTJb7kGqkzshRebClQvA=
+github.com/iotaledger/hive.go v0.0.0-20200720084404-e6c3b4717f40 h1:ip8DBCFeCHushgxy0oEWGY9/AfdIOzqjnxD2/yuRTlo=
+github.com/iotaledger/hive.go v0.0.0-20200720084404-e6c3b4717f40/go.mod h1:42UvBc41QBsuM7z1P1fABMonTJb7kGqkzshRebClQvA=
 github.com/iotaledger/iota.go v1.0.0-beta.15 h1:HI8PqerEnO1CCIqmXHJ6zh1IaSFXU+S0qlUAEKshho8=
 github.com/iotaledger/iota.go v1.0.0-beta.15/go.mod h1:Rn6v5hLAn8YBaJlRu1ZQdPAgKlshJR1PTeLQaft2778=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
diff --git a/packages/binary/drng/subtypes/collectiveBeacon/payload/payload.go b/packages/binary/drng/subtypes/collectiveBeacon/payload/payload.go
index d53be6f1..435ba79e 100644
--- a/packages/binary/drng/subtypes/collectiveBeacon/payload/payload.go
+++ b/packages/binary/drng/subtypes/collectiveBeacon/payload/payload.go
@@ -1,8 +1,6 @@
 package payload
 
 import (
-	"errors"
-	"fmt"
 	"sync"
 
 	"github.com/iotaledger/hive.go/stringify"
@@ -13,11 +11,6 @@ import (
 	"github.com/iotaledger/hive.go/marshalutil"
 )
 
-var (
-	// ErrMaximumPayloadSizeExceeded is returned if the payload exceeds the maximum size.
-	ErrMaximumPayloadSizeExceeded = errors.New("maximum payload size exceeded")
-)
-
 // Payload is a collective beacon payload.
 type Payload struct {
 	header.Header
@@ -35,9 +28,6 @@ type Payload struct {
 	bytesMutex sync.RWMutex
 }
 
-// MaxCollectiveBeaconPayloadSize defines the maximum size of a collective beacon payload.
-const MaxCollectiveBeaconPayloadSize = 64 * 1024
-
 // New creates a new collective beacon payload.
 func New(instanceID uint32, round uint64, prevSignature, signature, dpk []byte) *Payload {
 	return &Payload{
@@ -56,9 +46,7 @@ func Parse(marshalUtil *marshalutil.MarshalUtil) (*Payload, error) {
 		return nil, err
 	}
 	_payload := unmarshalledPayload.(*Payload)
-	if len(_payload.bytes) > MaxCollectiveBeaconPayloadSize {
-		return nil, fmt.Errorf("%w: %d", ErrMaximumPayloadSizeExceeded, MaxCollectiveBeaconPayloadSize)
-	}
+
 	return _payload, nil
 }
 
diff --git a/packages/binary/messagelayer/messagefactory/messagefactory.go b/packages/binary/messagelayer/messagefactory/messagefactory.go
index 4a206e2d..82311b00 100644
--- a/packages/binary/messagelayer/messagefactory/messagefactory.go
+++ b/packages/binary/messagelayer/messagefactory/messagefactory.go
@@ -14,6 +14,11 @@ import (
 
 const storeSequenceInterval = 100
 
+var (
+	// ZeroWorker is a PoW worker that always returns 0 as the nonce.
+	ZeroWorker = WorkerFunc(func([]byte) (uint64, error) { return 0, nil })
+)
+
 // A TipSelector selects two tips, branch and trunk, for a new message to attach to.
 type TipSelector interface {
 	Tips() (trunk message.Id, branch message.Id)
@@ -24,9 +29,6 @@ type Worker interface {
 	DoPOW([]byte) (nonce uint64, err error)
 }
 
-// ZeroWorker is a PoW worker that always returns 0 as the nonce.
-var ZeroWorker = WorkerFunc(func([]byte) (uint64, error) { return 0, nil })
-
 // MessageFactory acts as a factory to create new messages.
 type MessageFactory struct {
 	Events        *Events
@@ -65,13 +67,21 @@ func (m *MessageFactory) SetWorker(worker Worker) {
 // IssuePayload creates a new message including sequence number and tip selection and returns it.
 // It also triggers the MessageConstructed event once it's done, which is for example used by the plugins to listen for
 // messages that shall be attached to the tangle.
-func (m *MessageFactory) IssuePayload(payload payload.Payload) *message.Message {
+func (m *MessageFactory) IssuePayload(p payload.Payload) (*message.Message, error) {
+	payloadLen := len(p.Bytes())
+	if payloadLen > payload.MaxPayloadSize {
+		err := fmt.Errorf("%w: %d bytes", payload.ErrMaxPayloadSizeExceeded, payloadLen)
+		m.Events.Error.Trigger(err)
+		return nil, err
+	}
+
 	m.issuanceMutex.Lock()
 	defer m.issuanceMutex.Unlock()
 	sequenceNumber, err := m.sequence.Next()
 	if err != nil {
-		m.Events.Error.Trigger(fmt.Errorf("could not create sequence number: %w", err))
-		return nil
+		err = fmt.Errorf("could not create sequence number: %w", err)
+		m.Events.Error.Trigger(err)
+		return nil, err
 	}
 
 	trunkID, branchID := m.selector.Tips()
@@ -79,14 +89,15 @@ func (m *MessageFactory) IssuePayload(payload payload.Payload) *message.Message
 	issuerPublicKey := m.localIdentity.PublicKey()
 
 	// do the PoW
-	nonce, err := m.doPOW(trunkID, branchID, issuingTime, issuerPublicKey, sequenceNumber, payload)
+	nonce, err := m.doPOW(trunkID, branchID, issuingTime, issuerPublicKey, sequenceNumber, p)
 	if err != nil {
-		m.Events.Error.Trigger(fmt.Errorf("pow failed: %w", err))
-		return nil
+		err = fmt.Errorf("pow failed: %w", err)
+		m.Events.Error.Trigger(err)
+		return nil, err
 	}
 
 	// create the signature
-	signature := m.sign(trunkID, branchID, issuingTime, issuerPublicKey, sequenceNumber, payload, nonce)
+	signature := m.sign(trunkID, branchID, issuingTime, issuerPublicKey, sequenceNumber, p, nonce)
 
 	msg := message.New(
 		trunkID,
@@ -94,12 +105,12 @@ func (m *MessageFactory) IssuePayload(payload payload.Payload) *message.Message
 		issuingTime,
 		issuerPublicKey,
 		sequenceNumber,
-		payload,
+		p,
 		nonce,
 		signature,
 	)
 	m.Events.MessageConstructed.Trigger(msg)
-	return msg
+	return msg, nil
 }
 
 // Shutdown closes the messageFactory and persists the sequence number.
diff --git a/packages/binary/messagelayer/messagefactory/messagefactory_test.go b/packages/binary/messagelayer/messagefactory/messagefactory_test.go
index ad909fcf..5d56750b 100644
--- a/packages/binary/messagelayer/messagefactory/messagefactory_test.go
+++ b/packages/binary/messagelayer/messagefactory/messagefactory_test.go
@@ -16,6 +16,7 @@ import (
 	"github.com/iotaledger/hive.go/identity"
 	"github.com/iotaledger/hive.go/kvstore/mapdb"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 	_ "golang.org/x/crypto/blake2b"
 )
 
@@ -45,7 +46,8 @@ func TestMessageFactory_BuildMessage(t *testing.T) {
 
 	t.Run("CheckProperties", func(t *testing.T) {
 		p := payload.NewData([]byte("TestCheckProperties"))
-		msg := msgFactory.IssuePayload(p)
+		msg, err := msgFactory.IssuePayload(p)
+		require.NoError(t, err)
 
 		assert.NotNil(t, msg.TrunkId())
 		assert.NotNil(t, msg.BranchId())
@@ -70,7 +72,8 @@ func TestMessageFactory_BuildMessage(t *testing.T) {
 				t.Parallel()
 
 				p := payload.NewData([]byte("TestParallelCreation"))
-				msg := msgFactory.IssuePayload(p)
+				msg, err := msgFactory.IssuePayload(p)
+				require.NoError(t, err)
 
 				assert.NotNil(t, msg.TrunkId())
 				assert.NotNil(t, msg.BranchId())
@@ -125,7 +128,9 @@ func TestMessageFactory_POW(t *testing.T) {
 		return worker.Mine(context.Background(), content, targetPOW)
 	}))
 
-	msg := msgFactory.IssuePayload(payload.NewData([]byte("test")))
+	msg, err := msgFactory.IssuePayload(payload.NewData([]byte("test")))
+	require.NoError(t, err)
+
 	msgBytes := msg.Bytes()
 	content := msgBytes[:len(msgBytes)-ed25519.SignatureSize-8]
 
@@ -133,3 +138,26 @@ func TestMessageFactory_POW(t *testing.T) {
 	assert.GreaterOrEqual(t, zeroes, targetPOW)
 	assert.NoError(t, err)
 }
+
+func TestWorkerFunc_PayloadSize(t *testing.T) {
+	msgFactory := New(
+		mapdb.NewMapDB(),
+		[]byte(sequenceKey),
+		identity.GenerateLocalIdentity(),
+		TipSelectorFunc(func() (message.Id, message.Id) { return message.EmptyId, message.EmptyId }),
+	)
+	defer msgFactory.Shutdown()
+
+	// issue message with max allowed payload size
+	// dataPayload headers: type|32bit + size|32bit
+	data := make([]byte, payload.MaxPayloadSize-4-4)
+	msg, err := msgFactory.IssuePayload(payload.NewData(data))
+	require.NoError(t, err)
+	assert.Truef(t, payload.MaxMessageSize == len(msg.Bytes()), "message size should be exactly %d bytes but is %d", payload.MaxMessageSize, len(msg.Bytes()))
+
+	// issue message bigger than max allowed payload size
+	data = make([]byte, payload.MaxPayloadSize)
+	msg, err = msgFactory.IssuePayload(payload.NewData(data))
+	require.Error(t, err)
+	assert.Nil(t, msg)
+}
diff --git a/packages/binary/messagelayer/payload/data.go b/packages/binary/messagelayer/payload/data.go
index 6092956c..9db9cc64 100644
--- a/packages/binary/messagelayer/payload/data.go
+++ b/packages/binary/messagelayer/payload/data.go
@@ -14,9 +14,6 @@ type Data struct {
 	data        []byte
 }
 
-// MaxDataPayloadSize defines the maximum size of a data payload.
-const MaxDataPayloadSize = 64 * 1024
-
 // NewData creates new data payload.
 func NewData(data []byte) *Data {
 	return &Data{
diff --git a/packages/binary/messagelayer/payload/payload.go b/packages/binary/messagelayer/payload/payload.go
index a0282c32..689acbf7 100644
--- a/packages/binary/messagelayer/payload/payload.go
+++ b/packages/binary/messagelayer/payload/payload.go
@@ -1,20 +1,26 @@
 package payload
 
 import (
-	"errors"
 	"fmt"
 
 	"github.com/iotaledger/hive.go/marshalutil"
 )
 
-var (
-	// ErrMaximumPayloadSizeExceeded is returned if the payload exceeds the maximum size.
-	ErrMaximumPayloadSizeExceeded = errors.New("maximum payload size exceeded")
-)
-
 const (
 	// ObjectName defines the name of the data object.
 	ObjectName = "data"
+
+	// MaxMessageSize defines the maximum size of a message.
+	MaxMessageSize = 64 * 1024
+
+	// MaxPayloadSize defines the maximum size of a payload.
+	// trunkID + branchID + issuerPublicKey + issuingTime + sequenceNumber + nonce + signature
+	MaxPayloadSize = MaxMessageSize - 64 - 64 - 32 - 8 - 8 - 8 - 64
+)
+
+var (
+	// ErrMaxPayloadSizeExceeded is returned if the maximum payload size is exceeded.
+	ErrMaxPayloadSizeExceeded = fmt.Errorf("maximum payload size of %d bytes exceeded", MaxPayloadSize)
 )
 
 func init() {
@@ -53,8 +59,8 @@ func FromBytes(bytes []byte) (result Payload, consumedBytes int, err error) {
 		return
 	}
 
-	if payloadSize > MaxDataPayloadSize {
-		err = fmt.Errorf("%w: %d", ErrMaximumPayloadSizeExceeded, MaxDataPayloadSize)
+	if payloadSize > MaxPayloadSize {
+		err = fmt.Errorf("%w: %d", ErrMaxPayloadSizeExceeded, payloadSize)
 		return
 	}
 
diff --git a/packages/binary/messagelayer/test/data_payload_test.go b/packages/binary/messagelayer/test/data_payload_test.go
index 03d30b27..2ee00c52 100644
--- a/packages/binary/messagelayer/test/data_payload_test.go
+++ b/packages/binary/messagelayer/test/data_payload_test.go
@@ -10,6 +10,7 @@ import (
 	"github.com/iotaledger/hive.go/async"
 	"github.com/iotaledger/hive.go/identity"
 	"github.com/iotaledger/hive.go/kvstore/mapdb"
+	"github.com/stretchr/testify/require"
 
 	"github.com/panjf2000/ants/v2"
 
@@ -25,7 +26,9 @@ func BenchmarkVerifyDataMessages(b *testing.B) {
 
 	messages := make([][]byte, b.N)
 	for i := 0; i < b.N; i++ {
-		messages[i] = factory.IssuePayload(payload.NewData([]byte("some data"))).Bytes()
+		msg, err := factory.IssuePayload(payload.NewData([]byte("some data")))
+		require.NoError(b, err)
+		messages[i] = msg.Bytes()
 	}
 
 	b.ResetTimer()
@@ -51,7 +54,9 @@ func BenchmarkVerifySignature(b *testing.B) {
 
 	messages := make([]*message.Message, b.N)
 	for i := 0; i < b.N; i++ {
-		messages[i] = factory.IssuePayload(payload.NewData([]byte("test")))
+		msg, err := factory.IssuePayload(payload.NewData([]byte("some data")))
+		require.NoError(b, err)
+		messages[i] = msg
 		messages[i].Bytes()
 	}
 	b.ResetTimer()
diff --git a/packages/binary/messagelayer/test/message_test.go b/packages/binary/messagelayer/test/message_test.go
index fa5ed95d..99d1e11c 100644
--- a/packages/binary/messagelayer/test/message_test.go
+++ b/packages/binary/messagelayer/test/message_test.go
@@ -11,6 +11,7 @@ import (
 	"github.com/iotaledger/hive.go/identity"
 	"github.com/iotaledger/hive.go/kvstore/mapdb"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/message"
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload"
@@ -49,7 +50,8 @@ func TestMessage_MarshalUnmarshal(t *testing.T) {
 	msgFactory := messagefactory.New(mapdb.NewMapDB(), []byte(messagelayer.DBSequenceNumber), identity.GenerateLocalIdentity(), tipselector.New())
 	defer msgFactory.Shutdown()
 
-	testMessage := msgFactory.IssuePayload(payload.NewData([]byte("test")))
+	testMessage, err := msgFactory.IssuePayload(payload.NewData([]byte("test")))
+	require.NoError(t, err)
 	assert.Equal(t, true, testMessage.VerifySignature())
 
 	t.Log(testMessage)
diff --git a/packages/gossip/manager.go b/packages/gossip/manager.go
index e4c5e79a..ced57670 100644
--- a/packages/gossip/manager.go
+++ b/packages/gossip/manager.go
@@ -17,7 +17,8 @@ import (
 )
 
 const (
-	maxPacketSize = 64 * 1024
+	// maxPacketSize defines the maximum packet size allowed for gossip and bufferedconn.
+	maxPacketSize = 65 * 1024
 )
 
 // LoadMessageFunc defines a function that returns the message for the given id.
diff --git a/packages/gossip/neighbor.go b/packages/gossip/neighbor.go
index 76868f75..7f1d4414 100644
--- a/packages/gossip/neighbor.go
+++ b/packages/gossip/neighbor.go
@@ -51,7 +51,7 @@ func NewNeighbor(peer *peer.Peer, conn net.Conn, log *logger.Logger) *Neighbor {
 
 	return &Neighbor{
 		Peer:                  peer,
-		BufferedConnection:    buffconn.NewBufferedConnection(conn),
+		BufferedConnection:    buffconn.NewBufferedConnection(conn, maxPacketSize),
 		log:                   log,
 		queue:                 make(chan []byte, neighborQueueSize),
 		closing:               make(chan struct{}),
diff --git a/plugins/dashboard/faucet_routes.go b/plugins/dashboard/faucet_routes.go
index 41e11549..a545fc0d 100644
--- a/plugins/dashboard/faucet_routes.go
+++ b/plugins/dashboard/faucet_routes.go
@@ -44,9 +44,9 @@ func sendFaucetReq(addr address.Address) (res *ReqMsg, err error) {
 	if err != nil {
 		return nil, err
 	}
-	msg := messagelayer.MessageFactory().IssuePayload(faucetPayload)
-	if msg == nil {
-		return nil, errors.Wrapf(ErrInternalError, "Fail to send faucet request")
+	msg, err := messagelayer.MessageFactory().IssuePayload(faucetPayload)
+	if err != nil {
+		return nil, errors.Wrapf(ErrInternalError, "Failed to send faucet request: %s", err.Error())
 	}
 
 	r := &ReqMsg{
diff --git a/plugins/issuer/plugin.go b/plugins/issuer/plugin.go
index 85a997f9..680303e5 100644
--- a/plugins/issuer/plugin.go
+++ b/plugins/issuer/plugin.go
@@ -36,5 +36,11 @@ func IssuePayload(payload payload.Payload) (*message.Message, error) {
 	if !sync.Synced() {
 		return nil, fmt.Errorf("can't issue payload: %w", sync.ErrNodeNotSynchronized)
 	}
-	return messagelayer.MessageFactory().IssuePayload(payload), nil
+
+	msg, err := messagelayer.MessageFactory().IssuePayload(payload)
+	if err != nil {
+		return nil, err
+	}
+
+	return msg, nil
 }
diff --git a/plugins/webapi/data/plugin.go b/plugins/webapi/data/plugin.go
index 605ad8d8..04258ba7 100644
--- a/plugins/webapi/data/plugin.go
+++ b/plugins/webapi/data/plugin.go
@@ -1,7 +1,6 @@
 package data
 
 import (
-	"fmt"
 	"net/http"
 	"sync"
 
@@ -45,12 +44,6 @@ func broadcastData(c echo.Context) error {
 		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
 	}
 
-	dataPayload := payload.NewData(request.Data)
-	if len(dataPayload.Bytes()) > payload.MaxDataPayloadSize {
-		err := fmt.Errorf("%w: %d", payload.ErrMaximumPayloadSizeExceeded, payload.MaxDataPayloadSize)
-		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
-	}
-
 	msg, err := issuer.IssuePayload(payload.NewData(request.Data))
 	if err != nil {
 		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
diff --git a/plugins/webapi/faucet/plugin.go b/plugins/webapi/faucet/plugin.go
index 791bc2e4..0000eb64 100644
--- a/plugins/webapi/faucet/plugin.go
+++ b/plugins/webapi/faucet/plugin.go
@@ -1,6 +1,7 @@
 package faucet
 
 import (
+	"fmt"
 	"net/http"
 	goSync "sync"
 
@@ -64,9 +65,9 @@ func requestFunds(c echo.Context) error {
 	if err != nil {
 		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
 	}
-	msg := messagelayer.MessageFactory().IssuePayload(faucetPayload)
-	if msg == nil {
-		return c.JSON(http.StatusInternalServerError, Response{Error: "Fail to send faucetrequest"})
+	msg, err := messagelayer.MessageFactory().IssuePayload(faucetPayload)
+	if err != nil {
+		return c.JSON(http.StatusInternalServerError, Response{Error: fmt.Sprintf("Failed to send faucetrequest: %s", err.Error())})
 	}
 
 	return c.JSON(http.StatusOK, Response{ID: msg.Id().String()})
diff --git a/tools/docker-network/builder/docker-compose.builder.yml b/tools/docker-network/builder/docker-compose.builder.yml
index d94cbaf6..2c7a616f 100644
--- a/tools/docker-network/builder/docker-compose.builder.yml
+++ b/tools/docker-network/builder/docker-compose.builder.yml
@@ -9,6 +9,7 @@ services:
     volumes:
       - ../../..:/tmp/goshimmer:ro
       - goshimmer-cache:/go
+#      - ../../../../hive.go:/tmp/hive.go:ro
 
 volumes:
   goshimmer-cache:
diff --git a/tools/docker-network/run.sh b/tools/docker-network/run.sh
index 903fe83a..934c29a0 100755
--- a/tools/docker-network/run.sh
+++ b/tools/docker-network/run.sh
@@ -8,7 +8,14 @@ fi
 REPLICAS=$1
 
 echo "Build GoShimmer"
-docker-compose -f builder/docker-compose.builder.yml up
+docker-compose -f builder/docker-compose.builder.yml up --abort-on-container-exit --exit-code-from builder
+
+# check exit code of builder
+if [ $? -ne 0 ]
+then
+  echo "Building failed. Please fix and try again!"
+  exit 1
+fi
 
 echo "Run GoShimmer network"
 docker-compose up --scale peer_replica=$REPLICAS
diff --git a/tools/integration-tests/tester/go.mod b/tools/integration-tests/tester/go.mod
index 1feee38f..6e684969 100644
--- a/tools/integration-tests/tester/go.mod
+++ b/tools/integration-tests/tester/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/docker/go-units v0.4.0 // indirect
 	github.com/drand/drand v0.9.1
 	github.com/iotaledger/goshimmer v0.1.3
-	github.com/iotaledger/hive.go v0.0.0-20200713104016-55eaecb9d028
+	github.com/iotaledger/hive.go v0.0.0-20200720084404-e6c3b4717f40
 	github.com/mr-tron/base58 v1.2.0
 	github.com/opencontainers/go-digest v1.0.0 // indirect
 	github.com/stretchr/testify v1.6.1
diff --git a/tools/integration-tests/tester/go.sum b/tools/integration-tests/tester/go.sum
index 3a4532b5..ccc86947 100644
--- a/tools/integration-tests/tester/go.sum
+++ b/tools/integration-tests/tester/go.sum
@@ -260,8 +260,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
 github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
 github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/iotaledger/hive.go v0.0.0-20200713104016-55eaecb9d028 h1:GUKeANC04c4NE94Gs6rkbWfo9bfOkqtLwbnCGFLL+TY=
-github.com/iotaledger/hive.go v0.0.0-20200713104016-55eaecb9d028/go.mod h1:42UvBc41QBsuM7z1P1fABMonTJb7kGqkzshRebClQvA=
+github.com/iotaledger/hive.go v0.0.0-20200720084404-e6c3b4717f40 h1:ip8DBCFeCHushgxy0oEWGY9/AfdIOzqjnxD2/yuRTlo=
+github.com/iotaledger/hive.go v0.0.0-20200720084404-e6c3b4717f40/go.mod h1:42UvBc41QBsuM7z1P1fABMonTJb7kGqkzshRebClQvA=
 github.com/iotaledger/iota.go v1.0.0-beta.15/go.mod h1:Rn6v5hLAn8YBaJlRu1ZQdPAgKlshJR1PTeLQaft2778=
 github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
 github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
-- 
GitLab