Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit f3d3c65

Browse files
authored
Extract serializer/deserializer to hive.go (#290)
* Extract serialization/deserialization to hive.go repository. * Update hive.go dependency. * Move constants and serializer errors to hive.go * Move specific values back from hive.go * Update go.mod
1 parent cde7354 commit f3d3c65

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2839
-2520
lines changed

address.go

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"fmt"
77

8+
"github.com/iotaledger/hive.go/serializer"
89
"github.com/iotaledger/iota.go/v2/bech32"
910
"github.com/iotaledger/iota.go/v2/ed25519"
1011
"golang.org/x/crypto/blake2b"
@@ -31,12 +32,12 @@ const (
3132
// Ed25519AddressBytesLength is the length of an Ed25519 address.
3233
Ed25519AddressBytesLength = blake2b.Size256
3334
// Ed25519AddressSerializedBytesSize is the size of a serialized Ed25519 address with its type denoting byte.
34-
Ed25519AddressSerializedBytesSize = SmallTypeDenotationByteSize + Ed25519AddressBytesLength
35+
Ed25519AddressSerializedBytesSize = serializer.SmallTypeDenotationByteSize + Ed25519AddressBytesLength
3536
)
3637

3738
// Address describes a general address.
3839
type Address interface {
39-
Serializable
40+
serializer.Serializable
4041
fmt.Stringer
4142

4243
// Type returns the type of the address.
@@ -47,7 +48,7 @@ type Address interface {
4748
}
4849

4950
// AddressSelector implements SerializableSelectorFunc for address types.
50-
func AddressSelector(addressType uint32) (Serializable, error) {
51+
func AddressSelector(addressType uint32) (serializer.Serializable, error) {
5152
return newAddress(byte(addressType))
5253
}
5354

@@ -61,7 +62,7 @@ func newAddress(addressType byte) (address Address, err error) {
6162
}
6263

6364
func bech32String(hrp NetworkPrefix, addr Address) string {
64-
bytes, _ := addr.Serialize(DeSeriModeNoValidation)
65+
bytes, _ := addr.Serialize(serializer.DeSeriModeNoValidation)
6566
s, err := bech32.Encode(string(hrp), bytes)
6667
if err != nil {
6768
panic(err)
@@ -77,21 +78,21 @@ func ParseBech32(s string) (NetworkPrefix, Address, error) {
7778
}
7879

7980
if len(addrData) == 0 {
80-
return "", nil, ErrDeserializationNotEnoughData
81+
return "", nil, serializer.ErrDeserializationNotEnoughData
8182
}
8283

8384
addr, err := newAddress(addrData[0])
8485
if err != nil {
8586
return "", nil, err
8687
}
8788

88-
n, err := addr.Deserialize(addrData, DeSeriModePerformValidation)
89+
n, err := addr.Deserialize(addrData, serializer.DeSeriModePerformValidation)
8990
if err != nil {
9091
return "", nil, err
9192
}
9293

9394
if n != len(addrData) {
94-
return "", nil, ErrDeserializationNotAllConsumed
95+
return "", nil, serializer.ErrDeserializationNotAllConsumed
9596
}
9697

9798
return NetworkPrefix(hrp), addr, nil
@@ -134,23 +135,23 @@ func (edAddr *Ed25519Address) String() string {
134135
return hex.EncodeToString(edAddr[:])
135136
}
136137

137-
func (edAddr *Ed25519Address) Deserialize(data []byte, deSeriMode DeSerializationMode) (int, error) {
138-
if deSeriMode.HasMode(DeSeriModePerformValidation) {
139-
if err := checkMinByteLength(Ed25519AddressSerializedBytesSize, len(data)); err != nil {
138+
func (edAddr *Ed25519Address) Deserialize(data []byte, deSeriMode serializer.DeSerializationMode) (int, error) {
139+
if deSeriMode.HasMode(serializer.DeSeriModePerformValidation) {
140+
if err := serializer.CheckMinByteLength(Ed25519AddressSerializedBytesSize, len(data)); err != nil {
140141
return 0, fmt.Errorf("invalid Ed25519 address bytes: %w", err)
141142
}
142-
if err := checkTypeByte(data, AddressEd25519); err != nil {
143+
if err := serializer.CheckTypeByte(data, AddressEd25519); err != nil {
143144
return 0, fmt.Errorf("unable to deserialize Ed25519 address: %w", err)
144145
}
145146
}
146-
copy(edAddr[:], data[SmallTypeDenotationByteSize:])
147+
copy(edAddr[:], data[serializer.SmallTypeDenotationByteSize:])
147148
return Ed25519AddressSerializedBytesSize, nil
148149
}
149150

150-
func (edAddr *Ed25519Address) Serialize(deSeriMode DeSerializationMode) (data []byte, err error) {
151+
func (edAddr *Ed25519Address) Serialize(deSeriMode serializer.DeSerializationMode) (data []byte, err error) {
151152
var b [Ed25519AddressSerializedBytesSize]byte
152153
b[0] = AddressEd25519
153-
copy(b[SmallTypeDenotationByteSize:], edAddr[:])
154+
copy(b[serializer.SmallTypeDenotationByteSize:], edAddr[:])
154155
return b[:], nil
155156
}
156157

@@ -197,12 +198,12 @@ type jsonEd25519Address struct {
197198
Address string `json:"address"`
198199
}
199200

200-
func (j *jsonEd25519Address) ToSerializable() (Serializable, error) {
201+
func (j *jsonEd25519Address) ToSerializable() (serializer.Serializable, error) {
201202
addrBytes, err := hex.DecodeString(j.Address)
202203
if err != nil {
203204
return nil, fmt.Errorf("unable to decode address from JSON for Ed25519 address: %w", err)
204205
}
205-
if err := checkExactByteLength(len(addrBytes), Ed25519AddressBytesLength); err != nil {
206+
if err := serializer.CheckExactByteLength(len(addrBytes), Ed25519AddressBytesLength); err != nil {
206207
return nil, fmt.Errorf("unable to decode address from JSON for Ed25519 address: %w", err)
207208
}
208209
addr := &Ed25519Address{}

address_signer.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66

7+
"github.com/iotaledger/hive.go/serializer"
78
"github.com/iotaledger/iota.go/v2/ed25519"
89
)
910

@@ -17,13 +18,13 @@ var (
1718
// AddressSigner produces signatures for messages which get verified against a given address.
1819
type AddressSigner interface {
1920
// Sign produces the signature for the given message.
20-
Sign(addr Address, msg []byte) (signature Serializable, err error)
21+
Sign(addr Address, msg []byte) (signature serializer.Serializable, err error)
2122
}
2223

2324
// AddressSignerFunc implements the AddressSigner interface.
24-
type AddressSignerFunc func(addr Address, msg []byte) (signature Serializable, err error)
25+
type AddressSignerFunc func(addr Address, msg []byte) (signature serializer.Serializable, err error)
2526

26-
func (s AddressSignerFunc) Sign(addr Address, msg []byte) (signature Serializable, err error) {
27+
func (s AddressSignerFunc) Sign(addr Address, msg []byte) (signature serializer.Serializable, err error) {
2728
return s(addr, msg)
2829
}
2930

@@ -56,7 +57,7 @@ type InMemoryAddressSigner struct {
5657
addrKeys map[string]interface{}
5758
}
5859

59-
func (s *InMemoryAddressSigner) Sign(addr Address, msg []byte) (signature Serializable, err error) {
60+
func (s *InMemoryAddressSigner) Sign(addr Address, msg []byte) (signature serializer.Serializable, err error) {
6061
switch addr.(type) {
6162
case *Ed25519Address:
6263
maybePrvKey, ok := s.addrKeys[addr.String()]

address_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package iotago_test
22

33
import (
44
"errors"
5+
"github.com/iotaledger/hive.go/serializer"
56
"github.com/iotaledger/iota.go/v2/tpkg"
67
"testing"
78

@@ -29,21 +30,21 @@ func TestEd25519Address_Deserialize(t *testing.T) {
2930
_, edAddrData := tpkg.RandEd25519Address()
3031
return edAddrData[:iotago.Ed25519AddressSerializedBytesSize-1]
3132
}(),
32-
iotago.ErrDeserializationNotEnoughData,
33+
serializer.ErrDeserializationNotEnoughData,
3334
},
3435
}
3536

3637
for _, tt := range tests {
3738
t.Run(tt.name, func(t *testing.T) {
3839
edAddr := &iotago.Ed25519Address{}
39-
bytesRead, err := edAddr.Deserialize(tt.edAddrData, iotago.DeSeriModePerformValidation)
40+
bytesRead, err := edAddr.Deserialize(tt.edAddrData, serializer.DeSeriModePerformValidation)
4041
if tt.err != nil {
4142
assert.True(t, errors.Is(err, tt.err))
4243
return
4344
}
4445
assert.NoError(t, err)
4546
assert.Equal(t, len(tt.edAddrData), bytesRead)
46-
assert.Equal(t, tt.edAddrData[iotago.SmallTypeDenotationByteSize:], edAddr[:])
47+
assert.Equal(t, tt.edAddrData[serializer.SmallTypeDenotationByteSize:], edAddr[:])
4748
})
4849
}
4950
}
@@ -61,7 +62,7 @@ func TestEd25519Address_Serialize(t *testing.T) {
6162
}
6263
for _, tt := range tests {
6364
t.Run(tt.name, func(t *testing.T) {
64-
edData, err := tt.source.Serialize(iotago.DeSeriModePerformValidation)
65+
edData, err := tt.source.Serialize(serializer.DeSeriModePerformValidation)
6566
assert.NoError(t, err)
6667
assert.Equal(t, tt.target, edData)
6768
})

benches_test.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package iotago_test
22

33
import (
4+
"github.com/iotaledger/hive.go/serializer"
45
"github.com/iotaledger/iota.go/v2/tpkg"
56
"testing"
67

@@ -9,54 +10,54 @@ import (
910
)
1011

1112
func BenchmarkDeserializeWithValidationOneIOTxPayload(b *testing.B) {
12-
data, err := tpkg.OneInputOutputTransaction().Serialize(iotago.DeSeriModeNoValidation)
13+
data, err := tpkg.OneInputOutputTransaction().Serialize(serializer.DeSeriModeNoValidation)
1314
if err != nil {
1415
b.Fatal(err)
1516
}
1617

1718
target := &iotago.Transaction{}
18-
_, err = target.Deserialize(data, iotago.DeSeriModeNoValidation)
19+
_, err = target.Deserialize(data, serializer.DeSeriModeNoValidation)
1920
if err != nil {
2021
b.Fatal(err)
2122
}
2223

2324
b.ResetTimer()
2425
for i := 0; i < b.N; i++ {
25-
target.Deserialize(data, iotago.DeSeriModePerformValidation)
26+
target.Deserialize(data, serializer.DeSeriModePerformValidation)
2627
}
2728
}
2829

2930
func BenchmarkDeserializeWithoutValidationOneIOTxPayload(b *testing.B) {
30-
data, err := tpkg.OneInputOutputTransaction().Serialize(iotago.DeSeriModeNoValidation)
31+
data, err := tpkg.OneInputOutputTransaction().Serialize(serializer.DeSeriModeNoValidation)
3132
if err != nil {
3233
b.Fatal(err)
3334
}
3435

3536
target := &iotago.Transaction{}
36-
_, err = target.Deserialize(data, iotago.DeSeriModeNoValidation)
37+
_, err = target.Deserialize(data, serializer.DeSeriModeNoValidation)
3738
if err != nil {
3839
b.Fatal(err)
3940
}
4041

4142
b.ResetTimer()
4243
for i := 0; i < b.N; i++ {
43-
target.Deserialize(data, iotago.DeSeriModeNoValidation)
44+
target.Deserialize(data, serializer.DeSeriModeNoValidation)
4445
}
4546
}
4647

4748
func BenchmarkSerializeWithValidationOneIOTxPayload(b *testing.B) {
4849
txPayload := tpkg.OneInputOutputTransaction()
4950
b.ResetTimer()
5051
for i := 0; i < b.N; i++ {
51-
txPayload.Serialize(iotago.DeSeriModePerformValidation)
52+
txPayload.Serialize(serializer.DeSeriModePerformValidation)
5253
}
5354
}
5455

5556
func BenchmarkSerializeWithoutValidationOneIOTxPayload(b *testing.B) {
5657
sigTxPayload := tpkg.OneInputOutputTransaction()
5758
b.ResetTimer()
5859
for i := 0; i < b.N; i++ {
59-
sigTxPayload.Serialize(iotago.DeSeriModeNoValidation)
60+
sigTxPayload.Serialize(serializer.DeSeriModeNoValidation)
6061
}
6162
}
6263

consts.go

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,6 @@
11
package iotago
22

33
const (
4-
// OneByte is the byte size of a single byte.
5-
OneByte = 1
6-
// Int16ByteSize is the byte size of an int16.
7-
Int16ByteSize = 2
8-
// UInt16ByteSize is the byte size of a uint16.
9-
UInt16ByteSize = 2
10-
// Int32ByteSize is the byte size of an int32.
11-
Int32ByteSize = 4
12-
// UInt32ByteSize is the byte size of a uint32.
13-
UInt32ByteSize = 4
14-
// Float32ByteSize is the byte size of a float32.
15-
Float32ByteSize = 4
16-
// Int64ByteSize is the byte size of an int64.
17-
Int64ByteSize = 8
18-
// UInt64ByteSize is the byte size of an uint64.
19-
UInt64ByteSize = 8
20-
// Float64ByteSize is the byte size of a float64.
21-
Float64ByteSize = 8
22-
// TypeDenotationByteSize is the size of a type denotation.
23-
TypeDenotationByteSize = UInt32ByteSize
24-
// SmallTypeDenotationByteSize is the size of a type denotation for a small range of possible values.
25-
SmallTypeDenotationByteSize = OneByte
26-
// StructArrayLengthByteSize is the byte size of struct array lengths.
27-
StructArrayLengthByteSize = UInt16ByteSize
28-
// ByteArrayLengthByteSize is the byte size of byte array lengths.
29-
ByteArrayLengthByteSize = UInt32ByteSize
30-
// PayloadLengthByteSize is the size of the payload length denoting bytes.
31-
PayloadLengthByteSize = UInt32ByteSize
32-
// MinPayloadByteSize is the minimum size of a payload (together with its length denotation).
33-
MinPayloadByteSize = UInt32ByteSize + OneByte
344
// TokenSupply is the IOTA token supply.
355
TokenSupply = 2_779_530_283_277_761
366
)
37-
38-
// TypeDenotationType defines a type denotation.
39-
type TypeDenotationType byte
40-
41-
const (
42-
// TypeDenotationUint32 defines a denotation which defines a type ID by a uint32.
43-
TypeDenotationUint32 TypeDenotationType = iota
44-
// TypeDenotationByte defines a denotation which defines a type ID by a byte.
45-
TypeDenotationByte
46-
// TypeDenotationNone defines that there is no type denotation.
47-
TypeDenotationNone
48-
)

error.go

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
11
package iotago
22

33
import (
4-
"encoding/binary"
54
"errors"
6-
"fmt"
75
)
86

97
var (
10-
// ErrInvalidBytes gets returned when data is invalid for deserialization.
11-
ErrInvalidBytes = errors.New("invalid bytes")
12-
// ErrDeserializationTypeMismatch gets returned when a denoted type for a given object is mismatched.
13-
// For example, while trying to deserialize a signature unlock block, a reference unlock block is seen.
14-
ErrDeserializationTypeMismatch = errors.New("data type is invalid for deserialization")
158
// ErrUnsupportedPayloadType gets returned for unsupported payload types.
169
ErrUnsupportedPayloadType = errors.New("unsupported payload type")
1710
// ErrUnsupportedObjectType gets returned for unsupported object types.
@@ -30,61 +23,4 @@ var (
3023
ErrUnknownUnlockBlockType = errors.New("unknown unlock block type")
3124
// ErrUnknownSignatureType gets returned for unknown signature types.
3225
ErrUnknownSignatureType = errors.New("unknown signature type")
33-
// ErrUnknownArrayValidationMode gets returned for unknown array validation modes.
34-
ErrUnknownArrayValidationMode = errors.New("unknown array validation mode")
35-
// ErrArrayValidationMinElementsNotReached gets returned if the count of elements is too small.
36-
ErrArrayValidationMinElementsNotReached = errors.New("min count of elements within the array not reached")
37-
// ErrArrayValidationMaxElementsExceeded gets returned if the count of elements is too big.
38-
ErrArrayValidationMaxElementsExceeded = errors.New("max count of elements within the array exceeded")
39-
// ErrArrayValidationViolatesUniqueness gets returned if the array elements are not unique.
40-
ErrArrayValidationViolatesUniqueness = errors.New("array elements must be unique")
41-
// ErrArrayValidationOrderViolatesLexicalOrder gets returned if the array elements are not in lexical order.
42-
ErrArrayValidationOrderViolatesLexicalOrder = errors.New("array elements must be in their lexical order (byte wise)")
43-
// ErrDeserializationNotEnoughData gets returned if there is not enough data available to deserialize a given object.
44-
ErrDeserializationNotEnoughData = errors.New("not enough data for deserialization")
45-
// ErrDeserializationInvalidBoolValue gets returned when a bool value is tried to be read but it is neither 0 or 1.
46-
ErrDeserializationInvalidBoolValue = errors.New("invalid bool value")
47-
// ErrDeserializationLengthInvalid gets returned if a length denotation exceeds a specified limit.
48-
ErrDeserializationLengthInvalid = errors.New("length denotation invalid")
49-
// ErrDeserializationNotAllConsumed gets returned if not all bytes were consumed during deserialization of a given type.
50-
ErrDeserializationNotAllConsumed = errors.New("not all data has been consumed but should have been")
5126
)
52-
53-
// checkType checks that the denoted type equals the shouldType.
54-
func checkType(data []byte, shouldType uint32) error {
55-
if len(data) < 4 {
56-
return fmt.Errorf("%w: can't check type denotation", ErrDeserializationNotEnoughData)
57-
}
58-
actualType := binary.LittleEndian.Uint32(data)
59-
if actualType != shouldType {
60-
return fmt.Errorf("%w: type denotation must be %d but is %d", ErrDeserializationTypeMismatch, shouldType, actualType)
61-
}
62-
return nil
63-
}
64-
65-
// checkTypeByte checks that the denoted type byte equals the shouldType.
66-
func checkTypeByte(data []byte, shouldType byte) error {
67-
if data == nil || len(data) == 0 {
68-
return fmt.Errorf("%w: can't check type byte", ErrDeserializationNotEnoughData)
69-
}
70-
if data[0] != shouldType {
71-
return fmt.Errorf("%w: type denotation must be %d but is %d", ErrDeserializationTypeMismatch, shouldType, data[0])
72-
}
73-
return nil
74-
}
75-
76-
// checkExactByteLength checks that the given length equals exact.
77-
func checkExactByteLength(exact int, length int) error {
78-
if length != exact {
79-
return fmt.Errorf("%w: data must be at exact %d bytes long but is %d", ErrInvalidBytes, exact, length)
80-
}
81-
return nil
82-
}
83-
84-
// checkMinByteLength checks that length is min. min.
85-
func checkMinByteLength(min int, length int) error {
86-
if length < min {
87-
return fmt.Errorf("%w: data must be at least %d bytes long but is %d", ErrDeserializationNotEnoughData, min, length)
88-
}
89-
return nil
90-
}

fuzzing/indexation/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ go 1.16
55
replace github.com/iotaledger/iota.go/v2 => ./../..
66

77
require (
8-
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415 // indirect
8+
github.com/iotaledger/hive.go v0.0.0-20210907083658-27edf6b49375
99
github.com/iotaledger/iota.go/v2 v2.0.0-20210303080450-b3ab28991fc8
1010
)

0 commit comments

Comments
 (0)