diff --git a/dapps/faucet/packages/faucet_test.go b/dapps/faucet/packages/faucet_test.go index 2dfda0bc95086f2f571b1e192bf117ed78b42857..0cb37730e62dd5642de4a2dcd1152184347c64a4 100644 --- a/dapps/faucet/packages/faucet_test.go +++ b/dapps/faucet/packages/faucet_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -41,7 +42,7 @@ func TestIsFaucetReq(t *testing.T) { time.Now(), local.PublicKey(), 0, - tangle.NewDataPayload([]byte("data")), + payload.NewGenericDataPayload([]byte("data")), 0, ed25519.EmptySignature, ) diff --git a/dapps/faucet/packages/payload/payload.go b/dapps/faucet/packages/payload/payload.go index f9e73a977d61b26f327a53cbf67406b262902d44..f282bb832ef3ad4cabdd294a8101309f06796652 100644 --- a/dapps/faucet/packages/payload/payload.go +++ b/dapps/faucet/packages/payload/payload.go @@ -5,6 +5,7 @@ import ( "crypto" "fmt" + "github.com/iotaledger/goshimmer/packages/tangle/payload" // Only want to use init _ "golang.org/x/crypto/blake2b" @@ -23,13 +24,13 @@ const ( // Payload represents a request which contains an address for the faucet to send funds to. type Payload struct { - payloadType tangle.PayloadType + payloadType payload.Type address address.Address nonce uint64 } // Type represents the identifier for the faucet Payload type. -var Type = tangle.PayloadType(2) +var Type = payload.NewType(2, ObjectName, PayloadUnmarshaler) var powWorker = pow.New(crypto.BLAKE2b_512, 1) // New is the constructor of a Payload and creates a new Payload object from the given details. @@ -50,10 +51,6 @@ func New(addr address.Address, powTarget int) (*Payload, error) { return p, nil } -func init() { - tangle.RegisterPayloadType(Type, ObjectName, PayloadUnmarshaler) -} - // FromBytes parses the marshaled version of a Payload into an object. // It either returns a new Payload or fills an optionally provided Payload with the parsed information. func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) { @@ -66,7 +63,7 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) { err = fmt.Errorf("failed to unmarshal payload size of faucet payload from bytes: %w", err) return } - result.payloadType, err = marshalUtil.ReadUint32() + result.payloadType, err = payload.TypeFromMarshalUtil(marshalUtil) if err != nil { err = fmt.Errorf("failed to unmarshal payload type of faucet payload from bytes: %w", err) return @@ -95,7 +92,7 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) { } // Type returns the type of the faucet Payload. -func (p *Payload) Type() tangle.PayloadType { +func (p *Payload) Type() payload.Type { return p.payloadType } @@ -111,7 +108,7 @@ func (p *Payload) Bytes() []byte { // marshal the payload specific information marshalUtil.WriteUint32(uint32(address.Length + pow.NonceBytes)) - marshalUtil.WriteUint32(p.Type()) + marshalUtil.WriteBytes(p.Type().Bytes()) marshalUtil.WriteBytes(p.address.Bytes()) marshalUtil.WriteUint64(p.nonce) @@ -127,7 +124,7 @@ func (p *Payload) String() string { } // PayloadUnmarshaler sets the generic unmarshaler. -func PayloadUnmarshaler(data []byte) (payload tangle.Payload, err error) { +func PayloadUnmarshaler(data []byte) (payload payload.Payload, err error) { payload, _, err = FromBytes(data) if err != nil { err = fmt.Errorf("failed to unmarshal faucet payload from bytes: %w", err) diff --git a/dapps/valuetransfers/packages/payload/payload.go b/dapps/valuetransfers/packages/payload/payload.go index 5db6de0388715fd27eaf456eb8ca9e99a52f29f0..914925cbd416019cab51bcdf6b644d1c6f80e2a7 100644 --- a/dapps/valuetransfers/packages/payload/payload.go +++ b/dapps/valuetransfers/packages/payload/payload.go @@ -4,13 +4,13 @@ import ( "fmt" "sync" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/objectstorage" "github.com/iotaledger/hive.go/stringify" "golang.org/x/crypto/blake2b" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" - "github.com/iotaledger/goshimmer/packages/tangle" ) const ( @@ -184,10 +184,14 @@ func (p *Payload) String() string { // region Payload implementation /////////////////////////////////////////////////////////////////////////////////////// // Type represents the identifier which addresses the value Payload type. -const Type = tangle.PayloadType(1) +var Type = payload.NewType(1, ObjectName, func(data []byte) (payload payload.Payload, err error) { + payload, _, err = FromBytes(data) + + return +}) // Type returns the type of the Payload. -func (p *Payload) Type() tangle.PayloadType { +func (p *Payload) Type() payload.Type { return Type } @@ -221,7 +225,7 @@ func (p *Payload) ObjectStorageValue() (bytes []byte) { payloadLength := IDLength + IDLength + len(transferBytes) marshalUtil := marshalutil.New(marshalutil.UINT32_SIZE + marshalutil.UINT32_SIZE + payloadLength) marshalUtil.WriteUint32(uint32(payloadLength)) - marshalUtil.WriteUint32(Type) + marshalUtil.WriteBytes(Type.Bytes()) marshalUtil.WriteBytes(p.parent1PayloadID.Bytes()) marshalUtil.WriteBytes(p.parent2PayloadID.Bytes()) marshalUtil.WriteBytes(transferBytes) @@ -233,16 +237,8 @@ func (p *Payload) ObjectStorageValue() (bytes []byte) { return } -func init() { - tangle.RegisterPayloadType(Type, ObjectName, func(data []byte) (payload tangle.Payload, err error) { - payload, _, err = FromBytes(data) - - return - }) -} - // define contract (ensure that the struct fulfills the corresponding interface) -var _ tangle.Payload = &Payload{} +var _ payload.Payload = &Payload{} // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/dapps/valuetransfers/packages/tangle/signature_filter_test.go b/dapps/valuetransfers/packages/tangle/signature_filter_test.go index 1cb93f673908da24bd03d4af3b11811f10938252..0b388a7a5fc2b2183120bc814f611410add38f6f 100644 --- a/dapps/valuetransfers/packages/tangle/signature_filter_test.go +++ b/dapps/valuetransfers/packages/tangle/signature_filter_test.go @@ -10,6 +10,7 @@ import ( valuePayload "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/autopeering/peer" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/identity" @@ -80,14 +81,14 @@ func TestSignatureFilter(t *testing.T) { // 3. test message with an invalid value payload { // create a data payload - marshalUtil := marshalutil.New(tangle.NewDataPayload([]byte("test")).Bytes()) + marshalUtil := marshalutil.New(payload.NewGenericDataPayload([]byte("test")).Bytes()) // set the type to be a value payload marshalUtil.WriteSeek(4) - marshalUtil.WriteUint32(valuePayload.Type) + marshalUtil.WriteBytes(valuePayload.Type.Bytes()) // parse modified bytes back into a payload object - dataPayload, _, err := tangle.DataPayloadFromBytes(marshalUtil.Bytes()) + dataPayload, _, err := payload.GenericDataPayloadFromBytes(marshalUtil.Bytes()) require.NoError(t, err) // parse message bytes diff --git a/packages/drng/collective_beacon_payload.go b/packages/drng/collective_beacon_payload.go index 08aa611ad1ce3ea803436e8534357dc79d0a2393..a0ed1f829468000514de7b3490b363ec3987397f 100644 --- a/packages/drng/collective_beacon_payload.go +++ b/packages/drng/collective_beacon_payload.go @@ -4,9 +4,9 @@ import ( "fmt" "sync" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/stringify" - "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/hive.go/marshalutil" ) @@ -131,7 +131,7 @@ func (p *CollectiveBeaconPayload) Bytes() (bytes []byte) { payloadLength := HeaderLength + marshalutil.UINT64_SIZE + SignatureSize*2 + PublicKeySize marshalUtil := marshalutil.New(marshalutil.UINT32_SIZE + marshalutil.UINT32_SIZE + payloadLength) marshalUtil.WriteUint32(uint32(payloadLength)) - marshalUtil.WriteUint32(PayloadType) + marshalUtil.WriteBytes(PayloadType.Bytes()) marshalUtil.WriteBytes(p.Header.Bytes()) marshalUtil.WriteUint64(p.Round) marshalUtil.WriteBytes(p.PrevSignature) @@ -160,7 +160,7 @@ func (p *CollectiveBeaconPayload) String() string { // region Payload implementation /////////////////////////////////////////////////////////////////////////////////////// // Type returns the collective beacon payload type. -func (p *CollectiveBeaconPayload) Type() tangle.PayloadType { +func (p *CollectiveBeaconPayload) Type() payload.Type { return PayloadType } diff --git a/packages/drng/payload.go b/packages/drng/payload.go index 0b66bb18089df8906480a2542d1f139afc63ba4f..7abd6532d8e2d930d72b2dcb332c61600dc9b66f 100644 --- a/packages/drng/payload.go +++ b/packages/drng/payload.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/stringify" ) @@ -106,7 +106,7 @@ func (p *Payload) Bytes() (bytes []byte) { // marshal the payload specific information marshalUtil.WriteUint32(uint32(len(p.Data) + HeaderLength)) - marshalUtil.WriteUint32(PayloadType) + marshalUtil.WriteBytes(PayloadType.Bytes()) marshalUtil.WriteBytes(p.Header.Bytes()) marshalUtil.WriteBytes(p.Data[:]) @@ -126,10 +126,14 @@ func (p *Payload) String() string { // region Payload implementation /////////////////////////////////////////////////////////////////////////////////////// // PayloadType defines the type of the drng payload. -var PayloadType = tangle.PayloadType(111) +var PayloadType = payload.NewType(111, ObjectName, func(data []byte) (payload payload.Payload, err error) { + payload, _, err = FromBytes(data) + + return +}) // Type returns the type of the drng payload. -func (p *Payload) Type() tangle.PayloadType { +func (p *Payload) Type() payload.Type { return PayloadType } @@ -138,12 +142,4 @@ func (p *Payload) Marshal() (bytes []byte, err error) { return p.Bytes(), nil } -func init() { - tangle.RegisterPayloadType(PayloadType, ObjectName, func(data []byte) (payload tangle.Payload, err error) { - payload, _, err = FromBytes(data) - - return - }) -} - // // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/packages/spammer/spammer.go b/packages/spammer/spammer.go index 42f333e35c0e129df59cccbc4a6ea41fdcfea5ac..376e29a956ecb0fb77d0db3251a2816e47369fc6 100644 --- a/packages/spammer/spammer.go +++ b/packages/spammer/spammer.go @@ -4,13 +4,14 @@ import ( "sync/atomic" "time" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/types" "github.com/iotaledger/goshimmer/packages/tangle" ) // IssuePayloadFunc is a function which issues a payload. -type IssuePayloadFunc = func(payload tangle.Payload) (*tangle.Message, error) +type IssuePayloadFunc = func(payload payload.Payload) (*tangle.Message, error) // Spammer spams messages with a static data payload. type Spammer struct { @@ -48,7 +49,7 @@ func (spammer *Spammer) run(rate int, timeUnit time.Duration, processID int64) { } // we don't care about errors or the actual issued message - _, _ = spammer.issuePayloadFunc(tangle.NewDataPayload([]byte("SPAM"))) + _, _ = spammer.issuePayloadFunc(payload.NewGenericDataPayload([]byte("SPAM"))) currentSentCounter++ diff --git a/packages/tangle/message.go b/packages/tangle/message.go index fecb7c7a68c2508d9700b4f143be742585cb48e2..fbecedf1fbbd939db819c0dea03835262b79c80b 100644 --- a/packages/tangle/message.go +++ b/packages/tangle/message.go @@ -5,6 +5,7 @@ import ( "sync" "time" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/objectstorage" @@ -19,6 +20,9 @@ const ( // MessageIDLength defines the length of an MessageID. MessageIDLength = 64 + + // ContentIDLength contains the amount of bytes that a marshaled version of the ContentID contains. + ContentIDLength = MessageIDLength ) // ContentID identifies the content of a message without its parent1/parent2 ids. @@ -110,7 +114,7 @@ type Message struct { issuerPublicKey ed25519.PublicKey issuingTime time.Time sequenceNumber uint64 - payload Payload + payload payload.Payload nonce uint64 signature ed25519.Signature @@ -124,7 +128,7 @@ type Message struct { } // NewMessage creates a new message with the details provided by the issuer. -func NewMessage(parent1ID MessageID, parent2ID MessageID, issuingTime time.Time, issuerPublicKey ed25519.PublicKey, sequenceNumber uint64, payload Payload, nonce uint64, signature ed25519.Signature) (result *Message) { +func NewMessage(parent1ID MessageID, parent2ID MessageID, issuingTime time.Time, issuerPublicKey ed25519.PublicKey, sequenceNumber uint64, payload payload.Payload, nonce uint64, signature ed25519.Signature) (result *Message) { return &Message{ parent1ID: parent1ID, parent2ID: parent2ID, @@ -172,7 +176,7 @@ func MessageFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (result *Messa err = fmt.Errorf("failed to parse sequence number of the message: %w", err) return } - if result.payload, err = PayloadFromMarshalUtil(marshalUtil); err != nil { + if result.payload, err = payload.FromMarshalUtil(marshalUtil); err != nil { err = fmt.Errorf("failed to parse payload of the message: %w", err) return } @@ -282,7 +286,7 @@ func (m *Message) SequenceNumber() uint64 { } // Payload returns the payload of the message. -func (m *Message) Payload() Payload { +func (m *Message) Payload() payload.Payload { return m.payload } @@ -322,7 +326,7 @@ func (m *Message) ContentID() (result ContentID) { // calculates the message id. func (m *Message) calculateID() MessageID { return blake2b.Sum512( - marshalutil.New(MessageIDLength + MessageIDLength + PayloadIDLength). + marshalutil.New(MessageIDLength + MessageIDLength + ContentIDLength). WriteBytes(m.parent1ID.Bytes()). WriteBytes(m.parent2ID.Bytes()). WriteBytes(m.ContentID().Bytes()). diff --git a/packages/tangle/message_test.go b/packages/tangle/message_test.go index c7f5e08a88a092c4e105299592d06c2270d501cf..91ce680f36249429012c3e2542490101e7b8609a 100644 --- a/packages/tangle/message_test.go +++ b/packages/tangle/message_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/identity" "github.com/iotaledger/hive.go/kvstore/mapdb" @@ -13,7 +14,7 @@ import ( func TestMessage_VerifySignature(t *testing.T) { keyPair := ed25519.GenerateKeyPair() - pl := NewDataPayload([]byte("test")) + pl := payload.NewGenericDataPayload([]byte("test")) unsigned := NewMessage(EmptyMessageID, EmptyMessageID, time.Time{}, keyPair.PublicKey, 0, pl, 0, ed25519.Signature{}) assert.False(t, unsigned.VerifySignature()) @@ -29,7 +30,7 @@ func TestMessage_MarshalUnmarshal(t *testing.T) { msgFactory := NewMessageFactory(mapdb.NewMapDB(), []byte(DBSequenceNumber), identity.GenerateLocalIdentity(), NewMessageTipSelector()) defer msgFactory.Shutdown() - testMessage, err := msgFactory.IssuePayload(NewDataPayload([]byte("test"))) + testMessage, err := msgFactory.IssuePayload(payload.NewGenericDataPayload([]byte("test"))) require.NoError(t, err) assert.Equal(t, true, testMessage.VerifySignature()) diff --git a/packages/tangle/messagefactory.go b/packages/tangle/messagefactory.go index f517dd6e5cf81514d1818b1dcfe1c543009f1217..b2ba17af35f9bfe04cd6c46dc0f867c46ca6b471 100644 --- a/packages/tangle/messagefactory.go +++ b/packages/tangle/messagefactory.go @@ -5,6 +5,7 @@ import ( "sync" "time" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/identity" "github.com/iotaledger/hive.go/kvstore" @@ -65,10 +66,10 @@ func (f *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 (f *MessageFactory) IssuePayload(p Payload) (*Message, error) { +func (f *MessageFactory) IssuePayload(p payload.Payload) (*Message, error) { payloadLen := len(p.Bytes()) - if payloadLen > MaxPayloadSize { - err := fmt.Errorf("%w: %d bytes", ErrMaxPayloadSizeExceeded, payloadLen) + if payloadLen > payload.MaxSize { + err := fmt.Errorf("maximum payload size of %d bytes exceeded", payloadLen) f.Events.Error.Trigger(err) return nil, err } @@ -118,7 +119,7 @@ func (f *MessageFactory) Shutdown() { } } -func (f *MessageFactory) doPOW(parent1ID MessageID, parent2ID MessageID, issuingTime time.Time, key ed25519.PublicKey, seq uint64, payload Payload) (uint64, error) { +func (f *MessageFactory) doPOW(parent1ID MessageID, parent2ID MessageID, issuingTime time.Time, key ed25519.PublicKey, seq uint64, payload payload.Payload) (uint64, error) { // create a dummy message to simplify marshaling dummy := NewMessage(parent1ID, parent2ID, issuingTime, key, seq, payload, 0, ed25519.EmptySignature).Bytes() @@ -127,7 +128,7 @@ func (f *MessageFactory) doPOW(parent1ID MessageID, parent2ID MessageID, issuing return f.worker.DoPOW(dummy) } -func (f *MessageFactory) sign(parent1ID MessageID, parent2ID MessageID, issuingTime time.Time, key ed25519.PublicKey, seq uint64, payload Payload, nonce uint64) ed25519.Signature { +func (f *MessageFactory) sign(parent1ID MessageID, parent2ID MessageID, issuingTime time.Time, key ed25519.PublicKey, seq uint64, payload payload.Payload, nonce uint64) ed25519.Signature { // create a dummy message to simplify marshaling dummy := NewMessage(parent1ID, parent2ID, issuingTime, key, seq, payload, nonce, ed25519.EmptySignature) dummyBytes := dummy.Bytes() diff --git a/packages/tangle/messagefactory_test.go b/packages/tangle/messagefactory_test.go index 53ac21e84a082377970498c7384b804213214b83..304e0836091255069f2d93b5b03c4a5405be18a4 100644 --- a/packages/tangle/messagefactory_test.go +++ b/packages/tangle/messagefactory_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/iotaledger/goshimmer/packages/pow" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/identity" "github.com/iotaledger/hive.go/kvstore/mapdb" @@ -43,7 +44,7 @@ func TestMessageFactory_BuildMessage(t *testing.T) { })) t.Run("CheckProperties", func(t *testing.T) { - p := NewDataPayload([]byte("TestCheckProperties")) + p := payload.NewGenericDataPayload([]byte("TestCheckProperties")) msg, err := msgFactory.IssuePayload(p) require.NoError(t, err) @@ -69,7 +70,7 @@ func TestMessageFactory_BuildMessage(t *testing.T) { t.Run("test", func(t *testing.T) { t.Parallel() - p := NewDataPayload([]byte("TestParallelCreation")) + p := payload.NewGenericDataPayload([]byte("TestParallelCreation")) msg, err := msgFactory.IssuePayload(p) require.NoError(t, err) @@ -126,7 +127,7 @@ func TestMessageFactory_POW(t *testing.T) { return worker.Mine(context.Background(), content, targetPOW) })) - msg, err := msgFactory.IssuePayload(NewDataPayload([]byte("test"))) + msg, err := msgFactory.IssuePayload(payload.NewGenericDataPayload([]byte("test"))) require.NoError(t, err) msgBytes := msg.Bytes() @@ -148,14 +149,14 @@ func TestWorkerFunc_PayloadSize(t *testing.T) { // issue message with max allowed payload size // dataPayload headers: type|32bit + size|32bit - data := make([]byte, MaxPayloadSize-4-4) - msg, err := msgFactory.IssuePayload(NewDataPayload(data)) + data := make([]byte, payload.MaxSize-4-4) + msg, err := msgFactory.IssuePayload(payload.NewGenericDataPayload(data)) require.NoError(t, err) assert.Truef(t, MaxMessageSize == len(msg.Bytes()), "message size should be exactly %d bytes but is %d", MaxMessageSize, len(msg.Bytes())) // issue message bigger than max allowed payload size - data = make([]byte, MaxPayloadSize) - msg, err = msgFactory.IssuePayload(NewDataPayload(data)) + data = make([]byte, payload.MaxSize) + msg, err = msgFactory.IssuePayload(payload.NewGenericDataPayload(data)) require.Error(t, err) assert.Nil(t, msg) } diff --git a/packages/tangle/payload.go b/packages/tangle/payload.go deleted file mode 100644 index beecf71a5ac94dc529cee6b0ed9513184feac2a1..0000000000000000000000000000000000000000 --- a/packages/tangle/payload.go +++ /dev/null @@ -1,259 +0,0 @@ -package tangle - -import ( - "fmt" - "sync" - - "github.com/iotaledger/hive.go/marshalutil" - "github.com/iotaledger/hive.go/stringify" - "github.com/mr-tron/base58" -) - -const ( - // MaxPayloadSize defines the maximum size of a payload. - // parent1ID + parent2ID + issuerPublicKey + issuingTime + sequenceNumber + nonce + signature - MaxPayloadSize = MaxMessageSize - 64 - 64 - 32 - 8 - 8 - 8 - 64 - - // PayloadIDLength is the length of a data payload id. - PayloadIDLength = 64 - - // ObjectName defines the name of the data object. - ObjectName = "data" -) - -var ( - // ErrMaxPayloadSizeExceeded is returned if the maximum payload size is exceeded. - ErrMaxPayloadSizeExceeded = fmt.Errorf("maximum payload size of %d bytes exceeded", MaxPayloadSize) - - typeRegister = make(map[PayloadType]Definition) - typeRegisterMutex sync.RWMutex - genericUnmarshaler Unmarshaler -) - -// PayloadID represents the id of a data payload. -type PayloadID [PayloadIDLength]byte - -// Bytes returns the id as a byte slice backed by the original array, -// therefore it should not be modified. -func (id PayloadID) Bytes() []byte { - return id[:] -} - -func (id PayloadID) String() string { - return base58.Encode(id[:]) -} - -// PayloadType represents the type id of a payload. -type PayloadType = uint32 - -// Unmarshaler takes some data and unmarshals it into a payload. -type Unmarshaler func(data []byte) (Payload, error) - -// Definition defines the properties of a payload type. -type Definition struct { - Name string - Unmarshaler -} - -func init() { - // register the generic unmarshaler - SetGenericUnmarshaler(GenericPayloadUnmarshaler) -} - -// RegisterPayloadType registers a payload type with the given unmarshaler. -func RegisterPayloadType(payloadType PayloadType, payloadName string, unmarshaler Unmarshaler) { - typeRegisterMutex.Lock() - typeRegister[payloadType] = Definition{ - Name: payloadName, - Unmarshaler: unmarshaler, - } - typeRegisterMutex.Unlock() -} - -// GetUnmarshaler returns the unmarshaler for the given type if known or -// the generic unmarshaler if the given payload type has no associated unmarshaler. -func GetUnmarshaler(payloadType PayloadType) Unmarshaler { - typeRegisterMutex.RLock() - defer typeRegisterMutex.RUnlock() - - if definition, exists := typeRegister[payloadType]; exists { - return definition.Unmarshaler - } - - return genericUnmarshaler -} - -// SetGenericUnmarshaler sets the generic unmarshaler. -func SetGenericUnmarshaler(unmarshaler Unmarshaler) { - genericUnmarshaler = unmarshaler -} - -// Name returns the name of a given payload type. -func Name(payloadType PayloadType) string { - typeRegisterMutex.RLock() - defer typeRegisterMutex.RUnlock() - if definition, exists := typeRegister[payloadType]; exists { - return definition.Name - } - return ObjectName -} - -// Payload represents some kind of payload of data which only gains meaning by having -// corresponding node logic processing payloads of a given type. -type Payload interface { - // PayloadType returns the type of the payload. - Type() PayloadType - // Bytes returns the payload bytes. - Bytes() []byte - // String returns a human-friendly representation of the payload. - String() string -} - -// PayloadFromBytes unmarshals bytes into a payload. -func PayloadFromBytes(bytes []byte) (result Payload, consumedBytes int, err error) { - // initialize helper - marshalUtil := marshalutil.New(bytes) - - payloadSize, err := marshalUtil.ReadUint32() - if err != nil { - err = fmt.Errorf("failed to unmarshal payload size from bytes: %w", err) - return - } - - if payloadSize > MaxPayloadSize { - err = fmt.Errorf("%w: %d", ErrMaxPayloadSizeExceeded, payloadSize) - return - } - - // calculate result - payloadType, err := marshalUtil.ReadUint32() - if err != nil { - err = fmt.Errorf("failed to unmarshal payload type from bytes: %w", err) - return - } - - marshalUtil.ReadSeek(marshalUtil.ReadOffset() - marshalutil.UINT32_SIZE*2) - payloadBytes, err := marshalUtil.ReadBytes(int(payloadSize) + 8) - if err != nil { - err = fmt.Errorf("failed to unmarshal payload bytes from bytes: %w", err) - return - } - - readOffset := marshalUtil.ReadOffset() - result, err = GetUnmarshaler(payloadType)(payloadBytes) - if err != nil { - // fallback to the generic unmarshaler if registered type fails to unmarshal - marshalUtil.ReadSeek(readOffset) - result, err = GenericPayloadUnmarshaler(payloadBytes) - if err != nil { - err = fmt.Errorf("failed to unmarshal payload from bytes with generic unmarshaler: %w", err) - return - } - } - - // return the number of bytes we processed - consumedBytes = marshalUtil.ReadOffset() - return -} - -// PayloadFromMarshalUtil parses a payload by using the given marshal util. -func PayloadFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (Payload, error) { - payload, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return PayloadFromBytes(data) }) - if err != nil { - err = fmt.Errorf("failed to parse payload: %w", err) - return nil, err - } - return payload.(Payload), nil -} - -// DataType is the message type of a data payload. -var DataType = PayloadType(0) - -func init() { - // register the generic data payload type - RegisterPayloadType(DataType, ObjectName, GenericPayloadUnmarshaler) -} - -// DataPayload represents a payload which just contains a blob of data. -type DataPayload struct { - payloadType PayloadType - data []byte -} - -// NewDataPayload creates new data payload. -func NewDataPayload(data []byte) *DataPayload { - return &DataPayload{ - payloadType: DataType, - data: data, - } -} - -// DataPayloadFromBytes creates a new data payload from the given bytes. -func DataPayloadFromBytes(bytes []byte) (result *DataPayload, consumedBytes int, err error) { - marshalUtil := marshalutil.New(bytes) - result, err = DataPayloadFromMarshalUtil(marshalUtil) - consumedBytes = marshalUtil.ReadOffset() - - return -} - -// DataPayloadFromMarshalUtil parses a new data payload out of the given marshal util. -func DataPayloadFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (result *DataPayload, err error) { - // parse information - result = &DataPayload{} - payloadBytes, err := marshalUtil.ReadUint32() - if err != nil { - err = fmt.Errorf("failed to parse data payload size: %w", err) - return - } - result.payloadType, err = marshalUtil.ReadUint32() - if err != nil { - err = fmt.Errorf("failed to parse data payload type: %w", err) - return - } - result.data, err = marshalUtil.ReadBytes(int(payloadBytes)) - if err != nil { - err = fmt.Errorf("failed to parse data payload contest: %w", err) - return - } - - return -} - -// Type returns the payload type. -func (d *DataPayload) Type() PayloadType { - return d.payloadType -} - -// Data returns the data of the data payload. -func (d *DataPayload) Data() []byte { - return d.data -} - -// Bytes marshals the data payload into a sequence of bytes. -func (d *DataPayload) Bytes() []byte { - // initialize helper - marshalUtil := marshalutil.New() - - // marshal the payload specific information - marshalUtil.WriteUint32(uint32(len(d.data))) - marshalUtil.WriteUint32(d.Type()) - marshalUtil.WriteBytes(d.data[:]) - - // return result - return marshalUtil.Bytes() -} - -func (d *DataPayload) String() string { - return stringify.Struct("Data", - stringify.StructField("type", int(d.Type())), - stringify.StructField("data", string(d.Data())), - ) -} - -// GenericPayloadUnmarshaler is an unmarshaler for the generic data payload type. -func GenericPayloadUnmarshaler(data []byte) (payload Payload, err error) { - payload, _, err = DataPayloadFromBytes(data) - - return -} diff --git a/packages/tangle/payload/data.go b/packages/tangle/payload/data.go new file mode 100644 index 0000000000000000000000000000000000000000..a34c3bac7c845fd694445c367b683c7f09dce3f5 --- /dev/null +++ b/packages/tangle/payload/data.go @@ -0,0 +1,89 @@ +package payload + +import ( + "github.com/iotaledger/hive.go/marshalutil" + "github.com/iotaledger/hive.go/stringify" + "golang.org/x/xerrors" +) + +// GenericDataPayloadType is the Type of a generic GenericDataPayload. +var GenericDataPayloadType = NewType(0, "GenericDataPayloadType", GenericDataPayloadUnmarshaler) + +// GenericDataPayloadUnmarshaler is the UnmarshalerFunc of the GenericDataPayload which is also used as a unmarshaler for unknown Types. +func GenericDataPayloadUnmarshaler(data []byte) (Payload, error) { + return GenericDataPayloadFromMarshalUtil(marshalutil.New(data)) +} + +// GenericDataPayload represents a payload which just contains a blob of data. +type GenericDataPayload struct { + payloadType Type + data []byte +} + +// NewGenericDataPayload creates new GenericDataPayload. +func NewGenericDataPayload(data []byte) *GenericDataPayload { + return &GenericDataPayload{ + payloadType: GenericDataPayloadType, + data: data, + } +} + +// GenericDataPayloadFromBytes unmarshals a GenericDataPayload from a sequence of bytes. +func GenericDataPayloadFromBytes(bytes []byte) (genericDataPayload *GenericDataPayload, consumedBytes int, err error) { + marshalUtil := marshalutil.New(bytes) + if genericDataPayload, err = GenericDataPayloadFromMarshalUtil(marshalUtil); err != nil { + err = xerrors.Errorf("failed to parse GenericDataPayload from MarshalUtil: %w", err) + return + } + consumedBytes = marshalUtil.ReadOffset() + + return +} + +// GenericDataPayloadFromMarshalUtil unmarshals a GenericDataPayload using a MarshalUtil (for easier unmarshaling). +func GenericDataPayloadFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (genericDataPayload *GenericDataPayload, err error) { + payloadSize, err := marshalUtil.ReadUint32() + if err != nil { + err = xerrors.Errorf("failed to parse payload size (%v): %w", err, ErrParseBytesFailed) + return + } + + genericDataPayload = &GenericDataPayload{} + if genericDataPayload.payloadType, err = TypeFromMarshalUtil(marshalUtil); err != nil { + err = xerrors.Errorf("failed to parse Type from MarshalUtil: %w", err) + return + } + if genericDataPayload.data, err = marshalUtil.ReadBytes(int(payloadSize)); err != nil { + err = xerrors.Errorf("failed to parse data (%v): %w", err, ErrParseBytesFailed) + return + } + + return +} + +// Type returns the Type of the Payload. +func (g *GenericDataPayload) Type() Type { + return g.payloadType +} + +// Blob returns the contained data of the GenericDataPayload (without its type and size headers). +func (g *GenericDataPayload) Blob() []byte { + return g.data +} + +// Bytes returns a marshaled version of the Payload. +func (g *GenericDataPayload) Bytes() []byte { + return marshalutil.New(). + WriteUint32(uint32(len(g.data))). + WriteBytes(g.Type().Bytes()). + WriteBytes(g.Blob()). + Bytes() +} + +// String returns a human readable version of the Payload. +func (g *GenericDataPayload) String() string { + return stringify.Struct("GenericDataPayload", + stringify.StructField("type", g.Type()), + stringify.StructField("blob", g.Blob()), + ) +} diff --git a/packages/tangle/payload/errors.go b/packages/tangle/payload/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..b587ba959924892243062032a718105585dd7d7a --- /dev/null +++ b/packages/tangle/payload/errors.go @@ -0,0 +1,10 @@ +package payload + +import ( + "errors" +) + +var ( + // ErrParseBytesFailed is returned if information can not be parsed from a sequence of bytes. + ErrParseBytesFailed = errors.New("failed to parse bytes") +) diff --git a/packages/tangle/payload/payload.go b/packages/tangle/payload/payload.go new file mode 100644 index 0000000000000000000000000000000000000000..9868e7e9a8d18893aff0bc082c45d1e7c039e849 --- /dev/null +++ b/packages/tangle/payload/payload.go @@ -0,0 +1,73 @@ +package payload + +import ( + "fmt" + + "github.com/iotaledger/hive.go/marshalutil" + "golang.org/x/xerrors" +) + +// MaxSize defines the maximum allowed size of a marshaled Payload (in bytes). +const MaxSize = 65288 + +// Payload represents the generic interface for an object that can be embedded in Messages of the Tangle. +type Payload interface { + // Type returns the Type of the Payload. + Type() Type + + // Bytes returns a marshaled version of the Payload. + Bytes() []byte + + // String returns a human readable version of the Payload. + String() string +} + +// FromBytes unmarshals a Payload from a sequence of bytes. +func FromBytes(payloadBytes []byte) (payload Payload, consumedBytes int, err error) { + marshalUtil := marshalutil.New(payloadBytes) + if payload, err = FromMarshalUtil(marshalUtil); err != nil { + err = xerrors.Errorf("failed to parse Payload from MarshalUtil: %w", err) + return + } + consumedBytes = marshalUtil.ReadOffset() + + return +} + +// FromMarshalUtil unmarshals a Payload using a MarshalUtil (for easier unmarshaling). +func FromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (payload Payload, err error) { + payloadSize, err := marshalUtil.ReadUint32() + if err != nil { + err = xerrors.Errorf("failed to parse payload size (%v): %w", err, ErrParseBytesFailed) + return + } + if payloadSize > MaxSize { + err = xerrors.Errorf("maximum payload size of %d bytes exceeded: %w", MaxSize, ErrParseBytesFailed) + return + } + + payloadType, err := TypeFromMarshalUtil(marshalUtil) + if err != nil { + err = xerrors.Errorf("failed to unmarshal Type from MarshalUtil: %w", err) + return + } + + marshalUtil.ReadSeek(-marshalutil.UINT32_SIZE * 2) + payloadBytes, err := marshalUtil.ReadBytes(int(payloadSize) + 8) + if err != nil { + err = xerrors.Errorf("failed to unmarshal payload bytes (%v): %w", err, ErrParseBytesFailed) + return + } + + readOffset := marshalUtil.ReadOffset() + if payload, err = Unmarshaler(payloadType)(payloadBytes); err != nil { + marshalUtil.ReadSeek(readOffset) + + if payload, err = GenericDataPayloadUnmarshaler(payloadBytes); err != nil { + err = fmt.Errorf("failed to parse Payload with generic GenericDataPayloadUnmarshaler: %w", err) + return + } + } + + return +} diff --git a/packages/tangle/payload/type.go b/packages/tangle/payload/type.go new file mode 100644 index 0000000000000000000000000000000000000000..db776ad5f056d3c1bde7be4fdc33baaa8a2db265 --- /dev/null +++ b/packages/tangle/payload/type.go @@ -0,0 +1,93 @@ +package payload + +import ( + "encoding/binary" + "strconv" + "sync" + + "github.com/iotaledger/hive.go/marshalutil" + "golang.org/x/xerrors" +) + +// Type represents the Type of a payload. +type Type uint32 + +// typeMetadata holds additional information for registered Types. +type typeMetadata struct { + Name string + UnmarshalerFunc +} + +var ( + // typeRegister contains a map of all Types that where registered by the node. + typeRegister = make(map[Type]typeMetadata) + + // typeRegisterMutex is used to make synchronize the access to the previously defined map. + typeRegisterMutex sync.RWMutex +) + +// NewType creates and registers a new payload Type. +func NewType(typeNumber uint32, typeName string, typeUnmarshaler UnmarshalerFunc) (payloadType Type) { + payloadType = Type(typeNumber) + + typeRegisterMutex.Lock() + defer typeRegisterMutex.Unlock() + + if registeredType, typeRegisteredAlready := typeRegister[payloadType]; typeRegisteredAlready { + panic("payload type " + + typeName + "(" + strconv.FormatUint(uint64(typeNumber), 10) + ")" + + " tries to overwrite previously created type " + + registeredType.Name + "(" + strconv.FormatUint(uint64(typeNumber), 10) + ")") + } + + typeRegister[payloadType] = typeMetadata{ + Name: typeName, + UnmarshalerFunc: typeUnmarshaler, + } + + return +} + +// TypeFromBytes unmarshals a Type from a sequence of bytes. +func TypeFromBytes(typeBytes []byte) (typeResult Type, consumedBytes int, err error) { + marshalUtil := marshalutil.New(typeBytes) + if typeResult, err = TypeFromMarshalUtil(marshalUtil); err != nil { + err = xerrors.Errorf("failed to parse Type from MarshalUtil: %w", err) + return + } + consumedBytes = marshalUtil.ReadOffset() + + return +} + +// TypeFromMarshalUtil unmarshals a Type using a MarshalUtil (for easier unmarshaling). +func TypeFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (typeResult Type, err error) { + typeUint32, err := marshalUtil.ReadUint32() + if err != nil { + err = xerrors.Errorf("failed to parse type (%v): %w", err, ErrParseBytesFailed) + return + } + typeResult = Type(typeUint32) + + return +} + +// Bytes returns a marshaled version of the Type. +func (t Type) Bytes() (bytes []byte) { + bytes = make([]byte, 4) + binary.LittleEndian.PutUint32(bytes, uint32(t)) + + return +} + +// String returns a human readable version of the Type for debug purposes. +func (t Type) String() string { + typeRegisterMutex.RLock() + defer typeRegisterMutex.RUnlock() + + if definition, exists := typeRegister[t]; exists { + return definition.Name + "(" + strconv.FormatUint(uint64(t), 10) + ")" + } + + return "UnknownType(" + strconv.FormatUint(uint64(t), 10) + ")" +} diff --git a/packages/tangle/payload/unmarshaler.go b/packages/tangle/payload/unmarshaler.go new file mode 100644 index 0000000000000000000000000000000000000000..d340dcc1969ee956aaa12da57312d6ad7e5d3af8 --- /dev/null +++ b/packages/tangle/payload/unmarshaler.go @@ -0,0 +1,16 @@ +package payload + +// UnmarshalerFunc defines the function signature for functions that can unmarshal Payloads. +type UnmarshalerFunc func(data []byte) (Payload, error) + +// Unmarshaler returns the UnmarshalerFunc for the given Type or the GenericDataPayloadUnmarshaler if the Type is unknown. +func Unmarshaler(payloadType Type) UnmarshalerFunc { + typeRegisterMutex.RLock() + defer typeRegisterMutex.RUnlock() + + if definition, exists := typeRegister[payloadType]; exists { + return definition.UnmarshalerFunc + } + + return GenericDataPayloadUnmarshaler +} diff --git a/packages/tangle/payload_test.go b/packages/tangle/payload_test.go index 92512835a58ca46d87335b11896a8eeefa1b2631..28e78ce2b1bbaefe74b9e47a1dbd46fe6602ac1e 100644 --- a/packages/tangle/payload_test.go +++ b/packages/tangle/payload_test.go @@ -5,6 +5,7 @@ import ( "sync" "testing" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/async" "github.com/iotaledger/hive.go/identity" "github.com/iotaledger/hive.go/kvstore/mapdb" @@ -21,7 +22,7 @@ func BenchmarkVerifyDataMessages(b *testing.B) { messages := make([][]byte, b.N) for i := 0; i < b.N; i++ { - msg, err := factory.IssuePayload(NewDataPayload([]byte("some data"))) + msg, err := factory.IssuePayload(payload.NewGenericDataPayload([]byte("some data"))) require.NoError(b, err) messages[i] = msg.Bytes() } @@ -49,7 +50,7 @@ func BenchmarkVerifySignature(b *testing.B) { messages := make([]*Message, b.N) for i := 0; i < b.N; i++ { - msg, err := factory.IssuePayload(NewDataPayload([]byte("some data"))) + msg, err := factory.IssuePayload(payload.NewGenericDataPayload([]byte("some data"))) require.NoError(b, err) messages[i] = msg messages[i].Bytes() diff --git a/packages/tangle/tangle_test.go b/packages/tangle/tangle_test.go index 2407814aa18083e5b1f7c006ba4c83ac46c7e107..c8d5d3771dace96a29486693026d1116640cdc38 100644 --- a/packages/tangle/tangle_test.go +++ b/packages/tangle/tangle_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/datastructure/randommap" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/identity" @@ -120,7 +121,7 @@ func TestTangle_MissingMessages(t *testing.T) { // create a helper function that creates the messages createNewMessage := func() *Message { // issue the payload - msg, err := msgFactory.IssuePayload(NewDataPayload([]byte("0"))) + msg, err := msgFactory.IssuePayload(payload.NewGenericDataPayload([]byte("0"))) require.NoError(t, err) // remove a tip if the width of the tangle is reached diff --git a/packages/tangle/test_utils.go b/packages/tangle/test_utils.go index df737ae8873adbdc1a7bb10fbac4342e99a14e90..e0808bbe602871d2d1348589f45be4f4834a1011 100644 --- a/packages/tangle/test_utils.go +++ b/packages/tangle/test_utils.go @@ -3,17 +3,18 @@ package tangle import ( "time" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/crypto/ed25519" ) func newTestNonceMessage(nonce uint64) *Message { - return NewMessage(EmptyMessageID, EmptyMessageID, time.Time{}, ed25519.PublicKey{}, 0, NewDataPayload([]byte("test")), nonce, ed25519.Signature{}) + return NewMessage(EmptyMessageID, EmptyMessageID, time.Time{}, ed25519.PublicKey{}, 0, payload.NewGenericDataPayload([]byte("test")), nonce, ed25519.Signature{}) } func newTestDataMessage(payloadString string) *Message { - return NewMessage(EmptyMessageID, EmptyMessageID, time.Now(), ed25519.PublicKey{}, 0, NewDataPayload([]byte(payloadString)), 0, ed25519.Signature{}) + return NewMessage(EmptyMessageID, EmptyMessageID, time.Now(), ed25519.PublicKey{}, 0, payload.NewGenericDataPayload([]byte(payloadString)), 0, ed25519.Signature{}) } func newTestParentsDataMessage(payloadString string, parent1, parent2 MessageID) *Message { - return NewMessage(parent1, parent2, time.Now(), ed25519.PublicKey{}, 0, NewDataPayload([]byte(payloadString)), 0, ed25519.Signature{}) + return NewMessage(parent1, parent2, time.Now(), ed25519.PublicKey{}, 0, payload.NewGenericDataPayload([]byte(payloadString)), 0, ed25519.Signature{}) } diff --git a/plugins/dashboard/explorer_routes.go b/plugins/dashboard/explorer_routes.go index f1c84bfe8ffb0054803da20b8fed5a99a1a02800..d6a1b898554c7f71c3b0fb5cbb6b18727d1ff324 100644 --- a/plugins/dashboard/explorer_routes.go +++ b/plugins/dashboard/explorer_routes.go @@ -55,7 +55,7 @@ func createExplorerMessage(msg *tangle.Message) (*ExplorerMessage, error) { Parent1MessageID: msg.Parent1ID().String(), Parent2MessageID: msg.Parent2ID().String(), Solid: cachedMessageMetadata.Unwrap().IsSolid(), - PayloadType: msg.Payload().Type(), + PayloadType: uint32(msg.Payload().Type()), Payload: ProcessPayload(msg.Payload()), } diff --git a/plugins/dashboard/payload_handler.go b/plugins/dashboard/payload_handler.go index 797877395568552b607e68bde26f117d8d8dc516..049792c434871c96a5080c711fed8731d645ee96 100644 --- a/plugins/dashboard/payload_handler.go +++ b/plugins/dashboard/payload_handler.go @@ -6,7 +6,7 @@ import ( "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance" valuepayload "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload" "github.com/iotaledger/goshimmer/packages/drng" - "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" syncbeaconpayload "github.com/iotaledger/goshimmer/plugins/syncbeacon/payload" "github.com/iotaledger/hive.go/marshalutil" ) @@ -75,13 +75,13 @@ type Balance struct { // ProcessPayload returns different structs regarding to the // payload type. -func ProcessPayload(p tangle.Payload) interface{} { +func ProcessPayload(p payload.Payload) interface{} { switch p.Type() { - case tangle.DataType: + case payload.GenericDataPayloadType: // data payload return BasicPayload{ - ContentTitle: "Data", - Content: p.(*tangle.DataPayload).Data(), + ContentTitle: "GenericDataPayload", + Content: p.(*payload.GenericDataPayload).Blob(), } case faucetpayload.Type: // faucet payload @@ -107,7 +107,7 @@ func ProcessPayload(p tangle.Payload) interface{} { } // processDrngPayload handles the subtypes of Drng payload -func processDrngPayload(p tangle.Payload) (dp DrngPayload) { +func processDrngPayload(p payload.Payload) (dp DrngPayload) { var subpayload interface{} marshalUtil := marshalutil.New(p.Bytes()) drngPayload, _ := drng.PayloadFromMarshalUtil(marshalUtil) @@ -137,7 +137,7 @@ func processDrngPayload(p tangle.Payload) (dp DrngPayload) { } // processDrngPayload handles the subtypes of Drng payload -func processSyncBeaconPayload(p tangle.Payload) (dp SyncBeaconPayload) { +func processSyncBeaconPayload(p payload.Payload) (dp SyncBeaconPayload) { syncBeaconPayload, ok := p.(*syncbeaconpayload.Payload) if !ok { log.Info("could not cast payload to sync beacon object") @@ -150,7 +150,7 @@ func processSyncBeaconPayload(p tangle.Payload) (dp SyncBeaconPayload) { } // processValuePayload handles Value payload -func processValuePayload(p tangle.Payload) (vp ValuePayload) { +func processValuePayload(p payload.Payload) (vp ValuePayload) { marshalUtil := marshalutil.New(p.Bytes()) v, _ := valuepayload.Parse(marshalUtil) diff --git a/plugins/issuer/plugin.go b/plugins/issuer/plugin.go index 2d75f13ba9551d1278f0d202da7cbed85d30712b..253eecf62f3984918b5768028ccc54c39e13b895 100644 --- a/plugins/issuer/plugin.go +++ b/plugins/issuer/plugin.go @@ -5,6 +5,7 @@ import ( goSync "sync" "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/goshimmer/plugins/syncbeaconfollower" "github.com/iotaledger/hive.go/node" @@ -31,7 +32,7 @@ func configure(_ *node.Plugin) {} // IssuePayload issues a payload to the message layer. // If the node is not synchronized an error is returned. -func IssuePayload(payload tangle.Payload) (*tangle.Message, error) { +func IssuePayload(payload payload.Payload) (*tangle.Message, error) { if !syncbeaconfollower.Synced() { return nil, fmt.Errorf("can't issue payload: %w", syncbeaconfollower.ErrNodeNotSynchronized) } diff --git a/plugins/metrics/message.go b/plugins/metrics/message.go index c32fc9cf4db2ba0bdea93ad59166d92ee9c7e2cb..3476673ed951335d42048d584cc90014aad4add9 100644 --- a/plugins/metrics/message.go +++ b/plugins/metrics/message.go @@ -4,7 +4,7 @@ import ( "time" "github.com/iotaledger/goshimmer/packages/metrics" - "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/syncutils" "go.uber.org/atomic" @@ -49,7 +49,7 @@ var ( measuredReceivedMPS atomic.Uint64 // Number of messages per payload type since start of the node. - messageCountPerPayload = make(map[tangle.PayloadType]uint64) + messageCountPerPayload = make(map[payload.Type]uint64) // protect map from concurrent read/write. messageCountPerPayloadMutex syncutils.RWMutex @@ -66,17 +66,17 @@ func MessageTotalCountSinceStart() uint64 { } // MessageCountSinceStartPerPayload returns a map of message payload types and their count since the start of the node. -func MessageCountSinceStartPerPayload() map[tangle.PayloadType]uint64 { +func MessageCountSinceStartPerPayload() map[payload.Type]uint64 { messageCountPerPayloadMutex.RLock() defer messageCountPerPayloadMutex.RUnlock() // copy the original map - copy := make(map[tangle.PayloadType]uint64) + clone := make(map[payload.Type]uint64) for key, element := range messageCountPerPayload { - copy[key] = element + clone[key] = element } - return copy + return clone } // MessageTips returns the actual number of tips in the message tangle. @@ -122,7 +122,7 @@ func ReceivedMessagesPerSecond() uint64 { ////// Handling data updates and measuring ////// -func increasePerPayloadCounter(p tangle.PayloadType) { +func increasePerPayloadCounter(p payload.Type) { messageCountPerPayloadMutex.Lock() defer messageCountPerPayloadMutex.Unlock() diff --git a/plugins/metrics/message_test.go b/plugins/metrics/message_test.go index cdab7406b86051c7dc9fb24bcd42212dbb095f43..bd8ae636cb22a015ccddfa60793f9e114f3189a3 100644 --- a/plugins/metrics/message_test.go +++ b/plugins/metrics/message_test.go @@ -7,7 +7,7 @@ import ( valuepayload "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload" "github.com/iotaledger/goshimmer/packages/drng" "github.com/iotaledger/goshimmer/packages/metrics" - "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/hive.go/events" "github.com/magiconair/properties/assert" @@ -21,13 +21,13 @@ func TestMessageCountPerPayload(t *testing.T) { increasePerPayloadCounter(valuepayload.Type) } assert.Equal(t, MessageTotalCountSinceStart(), (uint64)(10)) - assert.Equal(t, MessageCountSinceStartPerPayload(), map[tangle.PayloadType]uint64{valuepayload.Type: 10}) + assert.Equal(t, MessageCountSinceStartPerPayload(), map[payload.Type]uint64{valuepayload.Type: 10}) // simulate attaching 5 drng payloads for i := 0; i < 5; i++ { increasePerPayloadCounter(drng.PayloadType) } assert.Equal(t, MessageTotalCountSinceStart(), (uint64)(15)) - assert.Equal(t, MessageCountSinceStartPerPayload(), map[tangle.PayloadType]uint64{valuepayload.Type: 10, drng.PayloadType: 5}) + assert.Equal(t, MessageCountSinceStartPerPayload(), map[payload.Type]uint64{valuepayload.Type: 10, drng.PayloadType: 5}) } func TestMessageTips(t *testing.T) { diff --git a/plugins/networkdelay/object.go b/plugins/networkdelay/object.go index a331e4b12cfe62122bc82e65501755f860058898..951d72e60993705c4b3c462c68a2621a34cac722 100644 --- a/plugins/networkdelay/object.go +++ b/plugins/networkdelay/object.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/stringify" "github.com/mr-tron/base58" @@ -111,7 +111,7 @@ func (o *Object) Bytes() (bytes []byte) { // marshal the payload specific information marshalUtil.WriteUint32(uint32(objectLength)) - marshalUtil.WriteUint32(Type) + marshalUtil.WriteBytes(Type.Bytes()) marshalUtil.WriteBytes(o.id[:]) marshalUtil.WriteInt64(o.sentTime) @@ -131,19 +131,15 @@ func (o *Object) String() string { // region Payload implementation /////////////////////////////////////////////////////////////////////////////////////// // Type represents the identifier which addresses the network delay Object type. -const Type = tangle.PayloadType(189) +var Type = payload.NewType(189, ObjectName, func(data []byte) (payload payload.Payload, err error) { + payload, _, err = FromBytes(data) + + return +}) // Type returns the type of the Object. -func (o *Object) Type() tangle.PayloadType { +func (o *Object) Type() payload.Type { return Type } -func init() { - tangle.RegisterPayloadType(Type, ObjectName, func(data []byte) (payload tangle.Payload, err error) { - payload, _, err = FromBytes(data) - - return - }) -} - // // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/prometheus/tangle.go b/plugins/prometheus/tangle.go index da20c98aa63dbd63bc004c4832e63c3230d66fd8..684e6098ef40497895ff5e24a34185196a8f7de3 100644 --- a/plugins/prometheus/tangle.go +++ b/plugins/prometheus/tangle.go @@ -1,7 +1,6 @@ package prometheus import ( - "github.com/iotaledger/goshimmer/packages/tangle" "github.com/iotaledger/goshimmer/plugins/metrics" "github.com/prometheus/client_golang/prometheus" ) @@ -92,7 +91,7 @@ func collectTangleMetrics() { messageTips.Set(float64(metrics.MessageTips())) msgCountPerPayload := metrics.MessageCountSinceStartPerPayload() for payloadType, count := range msgCountPerPayload { - messagePerTypeCount.WithLabelValues(tangle.Name(payloadType)).Set(float64(count)) + messagePerTypeCount.WithLabelValues(payloadType.String()).Set(float64(count)) } messageTotalCount.Set(float64(metrics.MessageTotalCountSinceStart())) messageTotalCountDB.Set(float64(metrics.MessageTotalCountDB())) diff --git a/plugins/syncbeacon/payload/payload.go b/plugins/syncbeacon/payload/payload.go index 59f4d547ae1cda174998a9fef5a11e0e4e1d9485..18fcbb38a2d39ce3da89551527f158c53a479cd0 100644 --- a/plugins/syncbeacon/payload/payload.go +++ b/plugins/syncbeacon/payload/payload.go @@ -3,7 +3,7 @@ package payload import ( "fmt" - "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/stringify" @@ -15,11 +15,15 @@ const ( ) // Type is the type of the syncbeacon payload. -var Type = tangle.PayloadType(200) +var Type = payload.NewType(200, ObjectName, func(data []byte) (payload payload.Payload, err error) { + payload, _, err = FromBytes(data) + + return +}) // Payload represents the syncbeacon payload type Payload struct { - payloadType tangle.PayloadType + payloadType payload.Type sentTime int64 } @@ -44,7 +48,7 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) { err = fmt.Errorf("failed to parse payload size of syncbeacon payload: %w", err) return } - result.payloadType, err = marshalUtil.ReadUint32() + result.payloadType, err = payload.TypeFromMarshalUtil(marshalUtil) if err != nil { err = fmt.Errorf("failed to parse payload type of syncbeacon payload: %w", err) return @@ -62,7 +66,7 @@ func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) { } // Type returns the type of the Payload. -func (p *Payload) Type() tangle.PayloadType { +func (p *Payload) Type() payload.Type { return p.payloadType } @@ -79,7 +83,7 @@ func (p *Payload) Bytes() []byte { // marshal the p specific information marshalUtil.WriteUint32(uint32(objectLength)) - marshalUtil.WriteUint32(Type) + marshalUtil.WriteBytes(Type.Bytes()) marshalUtil.WriteInt64(p.sentTime) // return result @@ -96,11 +100,3 @@ func (p *Payload) String() string { func IsSyncBeaconPayload(p *Payload) bool { return p.Type() == Type } - -func init() { - tangle.RegisterPayloadType(Type, ObjectName, func(data []byte) (payload tangle.Payload, err error) { - payload, _, err = FromBytes(data) - - return - }) -} diff --git a/plugins/webapi/data/plugin.go b/plugins/webapi/data/plugin.go index 96a31141d4649223157ea369bd908ff88034a03a..445296e0b770e8f432b153a5dbeff99dffc68ea6 100644 --- a/plugins/webapi/data/plugin.go +++ b/plugins/webapi/data/plugin.go @@ -4,7 +4,7 @@ import ( "net/http" "sync" - "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/goshimmer/plugins/issuer" "github.com/iotaledger/goshimmer/plugins/webapi" "github.com/iotaledger/hive.go/logger" @@ -44,7 +44,7 @@ func broadcastData(c echo.Context) error { return c.JSON(http.StatusBadRequest, Response{Error: err.Error()}) } - msg, err := issuer.IssuePayload(tangle.NewDataPayload(request.Data)) + msg, err := issuer.IssuePayload(payload.NewGenericDataPayload(request.Data)) if err != nil { return c.JSON(http.StatusBadRequest, Response{Error: err.Error()}) } diff --git a/plugins/webapi/message/sendPayload.go b/plugins/webapi/message/sendPayload.go index 61115bead14ab8fa37919308bab12ab1edfd3bad..725a0353a1ba82746099c8833939c4e36e6f731c 100644 --- a/plugins/webapi/message/sendPayload.go +++ b/plugins/webapi/message/sendPayload.go @@ -3,7 +3,7 @@ package message import ( "net/http" - "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/goshimmer/plugins/issuer" "github.com/labstack/echo" ) @@ -17,7 +17,7 @@ func sendPayloadHandler(c echo.Context) error { return c.JSON(http.StatusBadRequest, SendPayloadResponse{Error: err.Error()}) } - parsedPayload, _, err := tangle.PayloadFromBytes(request.Payload) + parsedPayload, _, err := payload.FromBytes(request.Payload) if err != nil { return c.JSON(http.StatusBadRequest, SendPayloadResponse{Error: err.Error()}) } diff --git a/tools/integration-tests/tester/tests/testutil.go b/tools/integration-tests/tester/tests/testutil.go index 3f8b586e5db902d63efe08cc4f594f7308abff81..328ee9d699726fe0bfd74e4b5f47057e09752073 100644 --- a/tools/integration-tests/tester/tests/testutil.go +++ b/tools/integration-tests/tester/tests/testutil.go @@ -13,7 +13,7 @@ import ( "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address/signaturescheme" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" - "github.com/iotaledger/goshimmer/packages/tangle" + "github.com/iotaledger/goshimmer/packages/tangle/payload" valueutils "github.com/iotaledger/goshimmer/plugins/webapi/value" "github.com/iotaledger/goshimmer/tools/integration-tests/tester/framework" "github.com/iotaledger/hive.go/types" @@ -70,7 +70,7 @@ func SendDataMessage(t *testing.T, peer *framework.Peer, data []byte, number int number: number, id: id, // save payload to be able to compare API response - data: tangle.NewDataPayload(data).Bytes(), + data: payload.NewGenericDataPayload(data).Bytes(), issuerPublicKey: peer.Identity.PublicKey().String(), } return id, sent