17
17
package sync
18
18
19
19
import (
20
+ "errors"
20
21
"math/big"
21
22
22
23
"github.com/ChainSafe/gossamer/dot/network"
@@ -25,122 +26,160 @@ import (
25
26
"github.com/ChainSafe/gossamer/lib/common/optional"
26
27
)
27
28
28
- var maxResponseSize int64 = 128 // maximum number of block datas to reply with in a BlockResponse message.
29
+ var maxResponseSize uint32 = 128 // maximum number of block datas to reply with in a BlockResponse message.
29
30
30
31
// CreateBlockResponse creates a block response message from a block request message
31
32
func (s * Service ) CreateBlockResponse (blockRequest * network.BlockRequestMessage ) (* network.BlockResponseMessage , error ) {
32
- var startHash common.Hash
33
- var endHash common.Hash
33
+ var (
34
+ startHash , endHash common.Hash
35
+ startHeader , endHeader * types.Header
36
+ err error
37
+ respSize uint32
38
+ )
34
39
35
40
if blockRequest .StartingBlock == nil {
36
41
return nil , ErrInvalidBlockRequest
37
42
}
38
43
44
+ if blockRequest .Max != nil && blockRequest .Max .Exists () {
45
+ respSize = blockRequest .Max .Value ()
46
+ if respSize > maxResponseSize {
47
+ respSize = maxResponseSize
48
+ }
49
+ } else {
50
+ respSize = maxResponseSize
51
+ }
52
+
39
53
switch startBlock := blockRequest .StartingBlock .Value ().(type ) {
40
54
case uint64 :
41
55
if startBlock == 0 {
42
56
startBlock = 1
43
57
}
44
- block , err := s .blockState .GetBlockByNumber (big .NewInt (0 ).SetUint64 (startBlock ))
58
+
59
+ block , err := s .blockState .GetBlockByNumber (big .NewInt (0 ).SetUint64 (startBlock )) //nolint
45
60
if err != nil {
46
61
return nil , err
47
62
}
48
63
64
+ startHeader = block .Header
49
65
startHash = block .Header .Hash ()
50
66
case common.Hash :
51
67
startHash = startBlock
68
+ startHeader , err = s .blockState .GetHeader (startHash )
69
+ if err != nil {
70
+ return nil , err
71
+ }
52
72
}
53
73
54
74
if blockRequest .EndBlockHash != nil && blockRequest .EndBlockHash .Exists () {
55
75
endHash = blockRequest .EndBlockHash .Value ()
76
+ endHeader , err = s .blockState .GetHeader (endHash )
77
+ if err != nil {
78
+ return nil , err
79
+ }
56
80
} else {
57
- endHash = s .blockState .BestBlockHash ()
58
- }
81
+ endNumber := big .NewInt (0 ).Add (startHeader .Number , big .NewInt (int64 (respSize - 1 )))
82
+ bestBlockNumber , err := s .blockState .BestBlockNumber ()
83
+ if err != nil {
84
+ return nil , err
85
+ }
59
86
60
- startHeader , err := s .blockState .GetHeader (startHash )
61
- if err != nil {
62
- return nil , err
63
- }
87
+ if endNumber .Cmp (bestBlockNumber ) == 1 {
88
+ endNumber = bestBlockNumber
89
+ }
64
90
65
- endHeader , err := s .blockState .GetHeader (endHash )
66
- if err != nil {
67
- return nil , err
91
+ endBlock , err := s .blockState .GetBlockByNumber (endNumber )
92
+ if err != nil {
93
+ return nil , err
94
+ }
95
+ endHeader = endBlock .Header
96
+ endHash = endHeader .Hash ()
68
97
}
69
98
70
99
logger .Debug ("handling BlockRequestMessage" , "start" , startHeader .Number , "end" , endHeader .Number , "startHash" , startHash , "endHash" , endHash )
71
100
72
- // get sub-chain of block hashes
73
- subchain , err := s .blockState .SubChain (startHash , endHash )
74
- if err != nil {
75
- return nil , err
76
- }
101
+ responseData := []* types.BlockData {}
77
102
78
- if len (subchain ) > int (maxResponseSize ) {
79
- subchain = subchain [:maxResponseSize ]
103
+ switch blockRequest .Direction {
104
+ case 0 : // ascending (ie child to parent)
105
+ for i := endHeader .Number .Int64 (); i >= startHeader .Number .Int64 (); i -- {
106
+ blockData , err := s .getBlockData (big .NewInt (i ), blockRequest .RequestedData )
107
+ if err != nil {
108
+ return nil , err
109
+ }
110
+ responseData = append (responseData , blockData )
111
+ }
112
+ case 1 : // descending (ie parent to child)
113
+ for i := startHeader .Number .Int64 (); i <= endHeader .Number .Int64 (); i ++ {
114
+ blockData , err := s .getBlockData (big .NewInt (i ), blockRequest .RequestedData )
115
+ if err != nil {
116
+ return nil , err
117
+ }
118
+ responseData = append (responseData , blockData )
119
+ }
120
+ default :
121
+ return nil , errors .New ("invalid BlockRequest direction" )
80
122
}
81
123
82
- logger .Trace ("subchain" , "start" , subchain [0 ], "end" , subchain [len (subchain )- 1 ])
83
-
84
- responseData := []* types.BlockData {}
124
+ logger .Debug ("sending BlockResponseMessage" , "start" , startHeader .Number , "end" , endHeader .Number )
125
+ return & network.BlockResponseMessage {
126
+ BlockData : responseData ,
127
+ }, nil
128
+ }
85
129
86
- // TODO: check ascending vs descending direction
87
- for _ , hash := range subchain {
130
+ func (s * Service ) getBlockData (num * big.Int , requestedData byte ) (* types.BlockData , error ) {
131
+ hash , err := s .blockState .GetHashByNumber (num )
132
+ if err != nil {
133
+ return nil , err
134
+ }
88
135
89
- blockData := new (types.BlockData )
90
- blockData .Hash = hash
136
+ blockData := & types.BlockData {
137
+ Hash : hash ,
138
+ Header : optional .NewHeader (false , nil ),
139
+ Body : optional .NewBody (false , nil ),
140
+ Receipt : optional .NewBytes (false , nil ),
141
+ MessageQueue : optional .NewBytes (false , nil ),
142
+ Justification : optional .NewBytes (false , nil ),
143
+ }
91
144
92
- // set defaults
93
- blockData .Header = optional .NewHeader (false , nil )
94
- blockData .Body = optional .NewBody (false , nil )
95
- blockData .Receipt = optional .NewBytes (false , nil )
96
- blockData .MessageQueue = optional .NewBytes (false , nil )
97
- blockData .Justification = optional .NewBytes (false , nil )
145
+ if requestedData == 0 {
146
+ return blockData , nil
147
+ }
98
148
99
- // header
100
- if (blockRequest .RequestedData & network .RequestedDataHeader ) == 1 {
101
- retData , err := s .blockState .GetHeader (hash )
102
- if err == nil && retData != nil {
103
- blockData .Header = retData .AsOptional ()
104
- }
149
+ if (requestedData & network .RequestedDataHeader ) == 1 {
150
+ retData , err := s .blockState .GetHeader (hash )
151
+ if err == nil && retData != nil {
152
+ blockData .Header = retData .AsOptional ()
105
153
}
154
+ }
106
155
107
- // body
108
- if (blockRequest .RequestedData & network .RequestedDataBody )>> 1 == 1 {
109
- retData , err := s .blockState .GetBlockBody (hash )
110
- if err == nil && retData != nil {
111
- blockData .Body = retData .AsOptional ()
112
- }
156
+ if (requestedData & network .RequestedDataBody )>> 1 == 1 {
157
+ retData , err := s .blockState .GetBlockBody (hash )
158
+ if err == nil && retData != nil {
159
+ blockData .Body = retData .AsOptional ()
113
160
}
161
+ }
114
162
115
- // receipt
116
- if (blockRequest .RequestedData & network .RequestedDataReceipt )>> 2 == 1 {
117
- retData , err := s .blockState .GetReceipt (hash )
118
- if err == nil && retData != nil {
119
- blockData .Receipt = optional .NewBytes (true , retData )
120
- }
163
+ if (requestedData & network .RequestedDataReceipt )>> 2 == 1 {
164
+ retData , err := s .blockState .GetReceipt (hash )
165
+ if err == nil && retData != nil {
166
+ blockData .Receipt = optional .NewBytes (true , retData )
121
167
}
168
+ }
122
169
123
- // message queue
124
- if (blockRequest .RequestedData & network .RequestedDataMessageQueue )>> 3 == 1 {
125
- retData , err := s .blockState .GetMessageQueue (hash )
126
- if err == nil && retData != nil {
127
- blockData .MessageQueue = optional .NewBytes (true , retData )
128
- }
170
+ if (requestedData & network .RequestedDataMessageQueue )>> 3 == 1 {
171
+ retData , err := s .blockState .GetMessageQueue (hash )
172
+ if err == nil && retData != nil {
173
+ blockData .MessageQueue = optional .NewBytes (true , retData )
129
174
}
175
+ }
130
176
131
- // justification
132
- if (blockRequest .RequestedData & network .RequestedDataJustification )>> 4 == 1 {
133
- retData , err := s .blockState .GetJustification (hash )
134
- if err == nil && retData != nil {
135
- blockData .Justification = optional .NewBytes (true , retData )
136
- }
177
+ if (requestedData & network .RequestedDataJustification )>> 4 == 1 {
178
+ retData , err := s .blockState .GetJustification (hash )
179
+ if err == nil && retData != nil {
180
+ blockData .Justification = optional .NewBytes (true , retData )
137
181
}
138
-
139
- responseData = append (responseData , blockData )
140
182
}
141
183
142
- logger .Debug ("sending BlockResponseMessage" , "start" , startHeader .Number , "end" , endHeader .Number )
143
- return & network.BlockResponseMessage {
144
- BlockData : responseData ,
145
- }, nil
184
+ return blockData , nil
146
185
}
0 commit comments