-
Notifications
You must be signed in to change notification settings - Fork 151
/
snapshot.go
90 lines (72 loc) · 2.97 KB
/
snapshot.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package utxo
import (
"encoding/binary"
"fmt"
"io"
"github.com/iotaledger/hive.go/serializer/v2"
"github.com/iotaledger/hive.go/serializer/v2/marshalutil"
iotago "github.com/iotaledger/iota.go/v3"
)
// Helpers to serialize/deserialize into/from snapshots
func (o *Output) SnapshotBytes() []byte {
m := marshalutil.New()
m.WriteBytes(o.outputID[:])
m.WriteBytes(o.blockID[:])
m.WriteUint32(o.msIndexBooked)
m.WriteUint32(o.msTimestampBooked)
m.WriteUint32(uint32(len(o.outputData)))
m.WriteBytes(o.outputData)
return m.Bytes()
}
func OutputFromSnapshotReader(reader io.ReadSeeker, protoParams *iotago.ProtocolParameters) (*Output, error) {
outputID := iotago.OutputID{}
if _, err := io.ReadFull(reader, outputID[:]); err != nil {
return nil, fmt.Errorf("unable to read LS output ID: %w", err)
}
blockID := iotago.BlockID{}
if _, err := io.ReadFull(reader, blockID[:]); err != nil {
return nil, fmt.Errorf("unable to read LS block ID: %w", err)
}
var msIndexBooked iotago.MilestoneIndex
if err := binary.Read(reader, binary.LittleEndian, &msIndexBooked); err != nil {
return nil, fmt.Errorf("unable to read LS output milestone index booked: %w", err)
}
var msTimestampBooked uint32
if err := binary.Read(reader, binary.LittleEndian, &msTimestampBooked); err != nil {
return nil, fmt.Errorf("unable to read LS output milestone timestamp booked: %w", err)
}
var outputLength uint32
if err := binary.Read(reader, binary.LittleEndian, &outputLength); err != nil {
return nil, fmt.Errorf("unable to read LS output length: %w", err)
}
outputBytes := make([]byte, outputLength)
if _, err := io.ReadFull(reader, outputBytes); err != nil {
return nil, fmt.Errorf("unable to read LS output bytes: %w", err)
}
output, err := iotago.OutputSelector(uint32(outputBytes[0]))
if err != nil {
return nil, fmt.Errorf("unable to determine output type of LS output: %w", err)
}
if _, err := output.Deserialize(outputBytes, serializer.DeSeriModePerformValidation, protoParams); err != nil {
return nil, fmt.Errorf("invalid LS output address: %w", err)
}
return CreateOutput(outputID, blockID, msIndexBooked, msTimestampBooked, output), nil
}
func (s *Spent) SnapshotBytes() []byte {
m := marshalutil.New()
m.WriteBytes(s.Output().SnapshotBytes())
m.WriteBytes(s.transactionIDSpent[:])
// we don't need to write msIndexSpent and msTimestampSpent because this info is available in the milestoneDiff that consumes the output
return m.Bytes()
}
func SpentFromSnapshotReader(reader io.ReadSeeker, protoParams *iotago.ProtocolParameters, msIndexSpent iotago.MilestoneIndex, msTimestampSpent uint32) (*Spent, error) {
output, err := OutputFromSnapshotReader(reader, protoParams)
if err != nil {
return nil, err
}
transactionIDSpent := iotago.TransactionID{}
if _, err := io.ReadFull(reader, transactionIDSpent[:]); err != nil {
return nil, fmt.Errorf("unable to read LS transaction ID spent: %w", err)
}
return NewSpent(output, transactionIDSpent, msIndexSpent, msTimestampSpent), nil
}