-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
service.go
92 lines (74 loc) · 2.24 KB
/
service.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
91
92
package header
import (
"context"
"crypto/sha256"
"encoding/binary"
"errors"
"time"
)
// Service defines the interface in which you can get header information
type Service interface {
HeaderInfo(context.Context) Info
}
// Info defines a struct that contains information about the header
type Info struct {
Height int64 // Height returns the height of the block
Hash []byte // Hash returns the hash of the block header
Time time.Time // Time returns the time of the block
AppHash []byte // AppHash used in the current block header
ChainID string // ChainId returns the chain ID of the block
}
const hashSize = sha256.Size
// Bytes encodes the Info struct into a byte slice using little-endian encoding
func (i *Info) Bytes() ([]byte, error) {
buf := make([]byte, 0)
// Encode Height
heightBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(heightBytes, uint64(i.Height))
buf = append(buf, heightBytes...)
// Encode Hash
if len(i.Hash) != hashSize {
return nil, errors.New("invalid Hash size")
}
buf = append(buf, i.Hash...)
// Encode Time
timeBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(timeBytes, uint64(i.Time.Unix()))
buf = append(buf, timeBytes...)
// Encode AppHash
if len(i.AppHash) != hashSize {
return nil, errors.New("invalid AppHash size")
}
buf = append(buf, i.AppHash...)
// Encode ChainID
chainIDLen := len(i.ChainID)
buf = append(buf, byte(chainIDLen))
buf = append(buf, []byte(i.ChainID)...)
return buf, nil
}
// FromBytes decodes the byte slice into an Info struct using little-endian encoding
func (i *Info) FromBytes(bytes []byte) error {
// Decode Height
i.Height = int64(binary.LittleEndian.Uint64(bytes[:8]))
bytes = bytes[8:]
// Decode Hash
i.Hash = make([]byte, hashSize)
copy(i.Hash, bytes[:hashSize])
bytes = bytes[hashSize:]
// Decode Time
unixTime := int64(binary.LittleEndian.Uint64(bytes[:8]))
i.Time = time.Unix(unixTime, 0).UTC()
bytes = bytes[8:]
// Decode AppHash
i.AppHash = make([]byte, hashSize)
copy(i.AppHash, bytes[:hashSize])
bytes = bytes[hashSize:]
// Decode ChainID
chainIDLen := int(bytes[0])
bytes = bytes[1:]
if len(bytes) < chainIDLen {
return errors.New("invalid byte slice length")
}
i.ChainID = string(bytes[:chainIDLen])
return nil
}