Skip to content
Snippets Groups Projects
Unverified Commit c3d21098 authored by Levente Pap's avatar Levente Pap
Browse files

Started refactoring msg structure

parent 4bbd582a
No related branches found
No related tags found
No related merge requests found
package tangle package tangle
import ( import (
"bytes"
"fmt" "fmt"
"sort"
"sync" "sync"
"time" "time"
"github.com/iotaledger/goshimmer/packages/tangle/payload" "github.com/iotaledger/goshimmer/packages/tangle/payload"
"github.com/iotaledger/hive.go/bitmask"
"github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/marshalutil"
"github.com/iotaledger/hive.go/objectstorage" "github.com/iotaledger/hive.go/objectstorage"
"github.com/iotaledger/hive.go/stringify" "github.com/iotaledger/hive.go/stringify"
"github.com/mr-tron/base58" "github.com/mr-tron/base58"
"golang.org/x/crypto/blake2b" "golang.org/x/crypto/blake2b"
"golang.org/x/xerrors"
) )
const ( const (
...@@ -19,10 +23,13 @@ const ( ...@@ -19,10 +23,13 @@ const (
MaxMessageSize = 64 * 1024 MaxMessageSize = 64 * 1024
// MessageIDLength defines the length of an MessageID. // MessageIDLength defines the length of an MessageID.
MessageIDLength = 64 MessageIDLength = 32
// ContentIDLength contains the amount of bytes that a marshaled version of the ContentID contains. // StrongParent identifies a strong parent in the bitmask.
ContentIDLength = MessageIDLength StrongParent uint8 = 1
// WeakParent identifies a weak parent in the bitmask.
WeakParent uint8 = 0
) )
// ContentID identifies the content of a message without its parent1/parent2 ids. // ContentID identifies the content of a message without its parent1/parent2 ids.
...@@ -32,6 +39,11 @@ type ContentID = MessageID ...@@ -32,6 +39,11 @@ type ContentID = MessageID
// the parent1 and parent2 ids. // the parent1 and parent2 ids.
type MessageID [MessageIDLength]byte type MessageID [MessageIDLength]byte
type Parent struct {
ID MessageID
Type uint8
}
// EmptyMessageID is an empty id. // EmptyMessageID is an empty id.
var EmptyMessageID = MessageID{} var EmptyMessageID = MessageID{}
...@@ -109,8 +121,9 @@ type Message struct { ...@@ -109,8 +121,9 @@ type Message struct {
objectstorage.StorableObjectFlags objectstorage.StorableObjectFlags
// core properties (get sent over the wire) // core properties (get sent over the wire)
parent1ID MessageID version uint8
parent2ID MessageID strongParents []MessageID
weakParents []MessageID
issuerPublicKey ed25519.PublicKey issuerPublicKey ed25519.PublicKey
issuingTime time.Time issuingTime time.Time
sequenceNumber uint64 sequenceNumber uint64
...@@ -121,8 +134,6 @@ type Message struct { ...@@ -121,8 +134,6 @@ type Message struct {
// derived properties // derived properties
id *MessageID id *MessageID
idMutex sync.RWMutex idMutex sync.RWMutex
contentID *ContentID
contentIDMutex sync.RWMutex
bytes []byte bytes []byte
bytesMutex sync.RWMutex bytesMutex sync.RWMutex
} }
...@@ -156,14 +167,37 @@ func MessageFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (result *Messa ...@@ -156,14 +167,37 @@ func MessageFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (result *Messa
// parse information // parse information
result = &Message{} result = &Message{}
if result.parent1ID, err = MessageIDFromMarshalUtil(marshalUtil); err != nil { if result.version, err = marshalUtil.ReadByte(); err != nil {
err = fmt.Errorf("failed to parse parent1 message ID of the message: %w", err) err = xerrors.Errorf("failed to parse message version from MarshalUtil: %w", err)
return return
} }
if result.parent2ID, err = MessageIDFromMarshalUtil(marshalUtil); err != nil {
err = fmt.Errorf("failed to parse parent1 message ID of the message: %w", err) parentsCount, err := marshalUtil.ReadByte()
if err != nil {
err = xerrors.Errorf("failed to parse parents count from MarshalUtil: %w", err)
return
}
parentTypes, err := marshalUtil.ReadByte()
if err != nil {
err = xerrors.Errorf("failed to parse parent types from MarshalUtil: %w", err)
return
}
bitMask := bitmask.BitMask(parentTypes)
for i := 0; i < int(parentsCount); i++ {
parentID, err := MessageIDFromMarshalUtil(marshalUtil)
if err != nil {
err = xerrors.Errorf("failed to parse parent %d from MarshalUtil: %w", i, err)
return return
} }
if bitMask.HasBit(uint(i)) {
result.strongParents = append(result.strongParents, parentID)
} else {
result.weakParents = append(result.weakParents, parentID)
}
// TODO: check if they are sorted
}
if result.issuerPublicKey, err = ed25519.ParsePublicKey(marshalUtil); err != nil { if result.issuerPublicKey, err = ed25519.ParsePublicKey(marshalUtil); err != nil {
err = fmt.Errorf("failed to parse issuer public key of the message: %w", err) err = fmt.Errorf("failed to parse issuer public key of the message: %w", err)
return return
...@@ -260,14 +294,8 @@ func (m *Message) ID() (result MessageID) { ...@@ -260,14 +294,8 @@ func (m *Message) ID() (result MessageID) {
return return
} }
// Parent1ID returns the id of the parent1 message. func (m *Message) ParentsCount() uint8 {
func (m *Message) Parent1ID() MessageID { return uint8(len(m.strongParents) + len(m.weakParents))
return m.parent1ID
}
// Parent2ID returns the id of the parent2 message.
func (m *Message) Parent2ID() MessageID {
return m.parent2ID
} }
// IssuerPublicKey returns the public key of the message issuer. // IssuerPublicKey returns the public key of the message issuer.
...@@ -300,67 +328,45 @@ func (m *Message) Signature() ed25519.Signature { ...@@ -300,67 +328,45 @@ func (m *Message) Signature() ed25519.Signature {
return m.signature return m.signature
} }
// ContentID returns the content id of the message which is made up of all the
// parts of the message minus the parent1 and parent2 ids.
func (m *Message) ContentID() (result ContentID) {
m.contentIDMutex.RLock()
if m.contentID == nil {
m.contentIDMutex.RUnlock()
m.contentIDMutex.Lock()
defer m.contentIDMutex.Unlock()
if m.contentID != nil {
result = *m.contentID
return
}
result = m.calculateContentID()
m.contentID = &result
return
}
result = *m.contentID
m.contentIDMutex.RUnlock()
return
}
// calculates the message id. // calculates the message id.
func (m *Message) calculateID() MessageID { func (m *Message) calculateID() MessageID {
return blake2b.Sum512( return blake2b.Sum256(m.Bytes())
marshalutil.New(MessageIDLength + MessageIDLength + ContentIDLength).
WriteBytes(m.parent1ID.Bytes()).
WriteBytes(m.parent2ID.Bytes()).
WriteBytes(m.ContentID().Bytes()).
Bytes(),
)
}
// calculates the content id of the message.
func (m *Message) calculateContentID() ContentID {
// compute content id from the message data (except parent1 and parent2 ids)
return blake2b.Sum512(m.Bytes()[2*MessageIDLength:])
} }
// Bytes returns the message in serialized byte form. // Bytes returns the message in serialized byte form.
func (m *Message) Bytes() []byte { func (m *Message) Bytes() []byte {
m.bytesMutex.RLock() m.bytesMutex.Lock()
if m.bytes != nil { defer m.bytesMutex.Unlock()
defer m.bytesMutex.RUnlock()
return m.bytes
}
m.bytesMutex.RUnlock()
m.bytesMutex.RLock()
defer m.bytesMutex.RUnlock()
if m.bytes != nil { if m.bytes != nil {
return m.bytes return m.bytes
} }
// marshal result // marshal result
marshalUtil := marshalutil.New() marshalUtil := marshalutil.New()
marshalUtil.WriteBytes(m.parent1ID.Bytes()) marshalUtil.WriteByte(m.version)
marshalUtil.WriteBytes(m.parent2ID.Bytes()) marshalUtil.WriteByte(m.ParentsCount())
parents := make([]Parent, 0, m.ParentsCount())
for _, parent := range m.strongParents {
parents = append(parents, Parent{ID: parent, Type: StrongParent})
}
for _, parent := range m.weakParents {
parents = append(parents, Parent{ID: parent, Type: WeakParent})
}
sort.Slice(parents, func(i, j int) bool {
return bytes.Compare(parents[i].ID.Bytes(), parents[j].ID.Bytes()) < 0
})
var bitMask bitmask.BitMask
for i, parent := range parents {
if parent.Type == StrongParent {
bitMask.SetBit(uint(i))
}
}
marshalUtil.WriteByte(byte(bitMask))
for _, parent := range parents {
marshalUtil.WriteBytes(parent.ID.Bytes())
}
marshalUtil.WriteBytes(m.issuerPublicKey.Bytes()) marshalUtil.WriteBytes(m.issuerPublicKey.Bytes())
marshalUtil.WriteTime(m.issuingTime) marshalUtil.WriteTime(m.issuingTime)
marshalUtil.WriteUint64(m.sequenceNumber) marshalUtil.WriteUint64(m.sequenceNumber)
......
...@@ -49,3 +49,7 @@ func TestMessage_MarshalUnmarshal(t *testing.T) { ...@@ -49,3 +49,7 @@ func TestMessage_MarshalUnmarshal(t *testing.T) {
assert.Equal(t, true, restoredMessage.VerifySignature()) assert.Equal(t, true, restoredMessage.VerifySignature())
} }
} }
// TODO: check if parents are sorted in Bytes()
// TODO: write unit tests
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment