forked from lesnikutsa/babylon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbtc_header_bytes.go
184 lines (151 loc) · 4.04 KB
/
btc_header_bytes.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package types
import (
"bytes"
"encoding/hex"
"encoding/json"
"errors"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/wire"
"math/big"
"time"
)
type BTCHeaderBytes []byte
const BTCHeaderLen = 80
func NewBTCHeaderBytesFromHex(hex string) (BTCHeaderBytes, error) {
var headerBytes BTCHeaderBytes
err := headerBytes.UnmarshalHex(hex)
if err != nil {
return nil, err
}
return headerBytes, nil
}
func NewBTCHeaderBytesFromBlockHeader(header *wire.BlockHeader) BTCHeaderBytes {
var headerBytes BTCHeaderBytes
headerBytes.FromBlockHeader(header)
return headerBytes
}
func NewBTCHeaderBytesFromBytes(header []byte) (BTCHeaderBytes, error) {
var headerBytes BTCHeaderBytes
err := headerBytes.Unmarshal(header)
if err != nil {
return nil, err
}
return headerBytes, nil
}
func (m BTCHeaderBytes) MarshalJSON() ([]byte, error) {
return json.Marshal(m.MarshalHex())
}
func (m *BTCHeaderBytes) UnmarshalJSON(bz []byte) error {
var headerHexStr string
err := json.Unmarshal(bz, &headerHexStr)
if err != nil {
return err
}
return m.UnmarshalHex(headerHexStr)
}
func (m BTCHeaderBytes) Marshal() ([]byte, error) {
return m, nil
}
func (m BTCHeaderBytes) MustMarshal() []byte {
bz, err := m.Marshal()
if err != nil {
panic("Marshalling failed")
}
return bz
}
func (m *BTCHeaderBytes) Unmarshal(data []byte) error {
if len(data) != BTCHeaderLen {
return errors.New("invalid header length")
}
// Verify that the bytes can be transformed to a *wire.BlockHeader object
_, err := toBlockHeader(data)
if err != nil {
return errors.New("bytes do not correspond to a *wire.BlockHeader object")
}
*m = data
return nil
}
func (m BTCHeaderBytes) MarshalHex() string {
btcdHeader := m.ToBlockHeader()
var buf bytes.Buffer
err := btcdHeader.Serialize(&buf)
if err != nil {
panic("Block header object cannot be converted to hex")
}
return hex.EncodeToString(buf.Bytes())
}
func (m *BTCHeaderBytes) UnmarshalHex(header string) error {
// Decode the hash string from hex
decoded, err := hex.DecodeString(header)
if err != nil {
return err
}
return m.Unmarshal(decoded)
}
func (m BTCHeaderBytes) MarshalTo(data []byte) (int, error) {
bz, err := m.Marshal()
if err != nil {
return 0, err
}
copy(data, bz)
return len(data), nil
}
func (m *BTCHeaderBytes) Size() int {
bz, _ := m.Marshal()
return len(bz)
}
func (m BTCHeaderBytes) ToBlockHeader() *wire.BlockHeader {
header, err := toBlockHeader(m)
// There was a parsing error
if err != nil {
panic("BTCHeaderBytes cannot be converted to a block header object")
}
return header
}
func (m *BTCHeaderBytes) FromBlockHeader(header *wire.BlockHeader) {
var buf bytes.Buffer
err := header.Serialize(&buf)
if err != nil {
panic("*wire.BlockHeader cannot be serialized")
}
err = m.Unmarshal(buf.Bytes())
if err != nil {
panic("*wire.BlockHeader serialized bytes cannot be unmarshalled")
}
}
func (m *BTCHeaderBytes) HasParent(header *BTCHeaderBytes) bool {
current := m.ToBlockHeader()
parent := header.ToBlockHeader()
return current.PrevBlock.String() == parent.BlockHash().String()
}
func (m *BTCHeaderBytes) Eq(other *BTCHeaderBytes) bool {
return m.Hash().Eq(other.Hash())
}
func (m *BTCHeaderBytes) Hash() *BTCHeaderHashBytes {
blockHash := m.ToBlockHeader().BlockHash()
hashBytes := NewBTCHeaderHashBytesFromChainhash(&blockHash)
return &hashBytes
}
func (m *BTCHeaderBytes) ParentHash() *BTCHeaderHashBytes {
parentHash := m.ToBlockHeader().PrevBlock
hashBytes := NewBTCHeaderHashBytesFromChainhash(&parentHash)
return &hashBytes
}
func (m *BTCHeaderBytes) Bits() uint32 {
return m.ToBlockHeader().Bits
}
func (m *BTCHeaderBytes) Time() time.Time {
return m.ToBlockHeader().Timestamp
}
func (m *BTCHeaderBytes) Difficulty() *big.Int {
return blockchain.CompactToBig(m.Bits())
}
func toBlockHeader(data []byte) (*wire.BlockHeader, error) {
// Create an empty header
header := &wire.BlockHeader{}
// The Deserialize method expects an io.Reader instance
reader := bytes.NewReader(data)
// Decode the header bytes
err := header.Deserialize(reader)
return header, err
}