From 6917bc13382add9fcd5de896ae9c20027ea75373 Mon Sep 17 00:00:00 2001 From: Hans Moog <hm@mkjc.net> Date: Thu, 19 Dec 2019 23:40:48 +0100 Subject: [PATCH] Feat: transactions support generic payload --- packages/binary/transaction/data_payload.go | 48 +++++++++++++++++++ packages/binary/transaction/payload.go | 2 +- packages/binary/transaction/payload_type.go | 3 ++ .../transaction/payload_type_register.go | 31 ++++++++++++ packages/binary/transaction/transaction.go | 26 +++++++--- .../binary/transaction/transaction_test.go | 4 +- 6 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 packages/binary/transaction/data_payload.go create mode 100644 packages/binary/transaction/payload_type.go create mode 100644 packages/binary/transaction/payload_type_register.go diff --git a/packages/binary/transaction/data_payload.go b/packages/binary/transaction/data_payload.go new file mode 100644 index 00000000..4b0de177 --- /dev/null +++ b/packages/binary/transaction/data_payload.go @@ -0,0 +1,48 @@ +package transaction + +type DataPayload struct { + payloadType PayloadType + data []byte +} + +var DataPayloadType = PayloadType(0) + +func NewDataPayload(data []byte) *DataPayload { + return &DataPayload{ + payloadType: DataPayloadType, + data: data, + } +} + +func (dataPayload *DataPayload) GetType() PayloadType { + return dataPayload.payloadType +} + +func (dataPayload *DataPayload) GetData() []byte { + return dataPayload.data +} + +func (dataPayload *DataPayload) UnmarshalBinary(data []byte) error { + dataPayload.data = make([]byte, len(data)) + copy(dataPayload.data, data) + + return nil +} + +func (dataPayload *DataPayload) MarshalBinary() (data []byte, err error) { + data = make([]byte, len(dataPayload.data)) + copy(data, dataPayload.data) + + return +} + +func createGenericDataPayloadUnmarshaler(payloadType PayloadType) PayloadUnmarshaler { + return func(data []byte) (payload Payload, err error) { + payload = &DataPayload{ + payloadType: payloadType, + } + err = payload.UnmarshalBinary(data) + + return + } +} diff --git a/packages/binary/transaction/payload.go b/packages/binary/transaction/payload.go index 13cb0d61..be68f2d9 100644 --- a/packages/binary/transaction/payload.go +++ b/packages/binary/transaction/payload.go @@ -8,5 +8,5 @@ type Payload interface { encoding.BinaryMarshaler encoding.BinaryUnmarshaler - GetType() int + GetType() PayloadType } diff --git a/packages/binary/transaction/payload_type.go b/packages/binary/transaction/payload_type.go new file mode 100644 index 00000000..23d4ca12 --- /dev/null +++ b/packages/binary/transaction/payload_type.go @@ -0,0 +1,3 @@ +package transaction + +type PayloadType = uint32 diff --git a/packages/binary/transaction/payload_type_register.go b/packages/binary/transaction/payload_type_register.go new file mode 100644 index 00000000..5dcb24ab --- /dev/null +++ b/packages/binary/transaction/payload_type_register.go @@ -0,0 +1,31 @@ +package transaction + +import ( + "sync" +) + +type PayloadUnmarshaler func(data []byte) (Payload, error) + +var ( + payloadTypeRegister map[PayloadType]PayloadUnmarshaler + payloadTypeRegisterMutex sync.RWMutex +) + +func RegisterPayloadType(payloadType PayloadType, unmarshaler PayloadUnmarshaler) { + payloadTypeRegisterMutex.Lock() + payloadTypeRegister[payloadType] = unmarshaler + payloadTypeRegisterMutex.Unlock() +} + +func GetPayloadUnmarshaler(payloadType PayloadType) PayloadUnmarshaler { + payloadTypeRegisterMutex.RLock() + if unmarshaler, exists := payloadTypeRegister[payloadType]; exists { + payloadTypeRegisterMutex.RUnlock() + + return unmarshaler + } else { + payloadTypeRegisterMutex.RUnlock() + + return createGenericDataPayloadUnmarshaler(payloadType) + } +} diff --git a/packages/binary/transaction/transaction.go b/packages/binary/transaction/transaction.go index a5b24d8d..f3e4f4fb 100644 --- a/packages/binary/transaction/transaction.go +++ b/packages/binary/transaction/transaction.go @@ -1,6 +1,7 @@ package transaction import ( + "encoding/binary" "sync" "github.com/iotaledger/goshimmer/packages/binary/identity" @@ -22,16 +23,16 @@ type Transaction struct { branchTransactionId Id issuer *identity.Identity payload Payload + bytes []byte + bytesMutex sync.RWMutex + signature [identity.SignatureSize]byte + signatureMutex sync.RWMutex // derived properties id *Id idMutex sync.RWMutex payloadId *PayloadId payloadIdMutex sync.RWMutex - bytes []byte - bytesMutex sync.RWMutex - signature [identity.SignatureSize]byte - signatureMutex sync.RWMutex } // Allows us to "issue" a transaction. @@ -97,6 +98,10 @@ func (transaction *Transaction) GetId() (result Id) { return } +func (transaction *Transaction) GetPayload() Payload { + return transaction.payload +} + func (transaction *Transaction) GetPayloadId() (result PayloadId) { transaction.payloadIdMutex.RLock() if transaction.payloadId == nil { @@ -168,7 +173,7 @@ func (transaction *Transaction) MarshalBinary() (result []byte, err error) { } serializedPayloadLength := len(serializedPayload) - result = make([]byte, transactionIdLength+transactionIdLength+identity.PublicKeySize+serializedPayloadLength+identity.SignatureSize) + result = make([]byte, transactionIdLength+transactionIdLength+identity.PublicKeySize+4+serializedPayloadLength+identity.SignatureSize) offset := 0 copy(result[offset:], transaction.trunkTransactionId[:]) @@ -180,7 +185,8 @@ func (transaction *Transaction) MarshalBinary() (result []byte, err error) { copy(result[offset:], transaction.issuer.PublicKey) offset += identity.PublicKeySize - // TODO: MARSHAL PAYLOAD LENGTH + binary.LittleEndian.PutUint32(result[offset:], transaction.payload.GetType()) + offset += 4 if serializedPayloadLength != 0 { copy(result[offset:], serializedPayload) @@ -219,7 +225,13 @@ func (transaction *Transaction) UnmarshalBinary(data []byte) (err error) { transaction.issuer = identity.New(data[offset : offset+identity.PublicKeySize]) offset += identity.PublicKeySize - // TODO: UNMARSHAL PAYLOAD LENGTH + CONTENT + payloadType := binary.LittleEndian.Uint32(data[offset:]) + offset += 4 + + if transaction.payload, err = GetPayloadUnmarshaler(payloadType)(data[offset : len(data)-identity.SignatureSize]); err != nil { + return + } + offset += len(data) - identity.SignatureSize - offset copy(transaction.signature[:], data[offset:]) // offset += identity.SignatureSize diff --git a/packages/binary/transaction/transaction_test.go b/packages/binary/transaction/transaction_test.go index e2082701..8d930a05 100644 --- a/packages/binary/transaction/transaction_test.go +++ b/packages/binary/transaction/transaction_test.go @@ -10,10 +10,10 @@ import ( ) func TestNew(t *testing.T) { - newTransaction1 := New(Id{}, Id{}, identity.Generate(), nil) + newTransaction1 := New(Id{}, Id{}, identity.Generate(), NewDataPayload([]byte("test"))) assert.Equal(t, newTransaction1.VerifySignature(), true) - newTransaction2 := New(newTransaction1.GetId(), Id{}, identity.Generate(), nil) + newTransaction2 := New(newTransaction1.GetId(), Id{}, identity.Generate(), NewDataPayload([]byte("test1"))) assert.Equal(t, newTransaction2.VerifySignature(), true) newTransaction3, _ := FromBytes(newTransaction2.GetBytes()) -- GitLab