@@ -14,8 +14,11 @@ import (
14
14
15
15
"github.com/nspcc-dev/neo-go/pkg/config"
16
16
"github.com/nspcc-dev/neo-go/pkg/core/block"
17
+ "github.com/nspcc-dev/neo-go/pkg/core/transaction"
18
+ "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
17
19
gio "github.com/nspcc-dev/neo-go/pkg/io"
18
20
"github.com/nspcc-dev/neo-go/pkg/services/helpers/neofs"
21
+ "github.com/nspcc-dev/neo-go/pkg/smartcontract"
19
22
"github.com/nspcc-dev/neo-go/pkg/wallet"
20
23
"github.com/nspcc-dev/neofs-sdk-go/client"
21
24
"github.com/nspcc-dev/neofs-sdk-go/container"
@@ -59,12 +62,12 @@ type Service struct {
59
62
log * zap.Logger
60
63
cfg config.NeoFSBlockFetcher
61
64
stateRootInHeader bool
62
-
63
- chain Ledger
64
- pool poolWrapper
65
- enqueueBlock func (* block.Block ) error
66
- enqueueHeader func (* block.Header ) error
67
- account * wallet.Account
65
+ headerSize int
66
+ chain Ledger
67
+ pool poolWrapper
68
+ enqueueBlock func (* block.Block ) error
69
+ enqueueHeader func (* block.Header ) error
70
+ account * wallet.Account
68
71
69
72
oidsCh chan oid.ID
70
73
// wg is a wait group for block downloaders.
@@ -140,6 +143,18 @@ func New(chain Ledger, cfg config.NeoFSBlockFetcher, logger *zap.Logger, putBloc
140
143
if err != nil {
141
144
return nil , err
142
145
}
146
+
147
+ getCfg := chain .GetConfig ()
148
+ m := smartcontract .GetDefaultHonestNodeCount (int (getCfg .ValidatorsCount ))
149
+ baseHeaderSize := block .New (chain .GetConfig ().StateRootInHeader ).GetExpectedHeaderSize () - 2
150
+ vs , _ := keys .NewPublicKeysFromStrings (getCfg .StandbyCommittee )
151
+ verification , _ := smartcontract .CreateDefaultMultiSigRedeemScript (vs [:getCfg .GetNumOfCNs (0 )])
152
+ defaultWitness := transaction.Witness {
153
+ InvocationScript : make ([]byte , 66 * m ),
154
+ VerificationScript : verification ,
155
+ }
156
+ w := gio .NewBufBinWriter ()
157
+ defaultWitness .EncodeBinary (w .BinWriter )
143
158
return & Service {
144
159
chain : chain ,
145
160
pool : poolWrapper {Pool : p },
@@ -150,6 +165,7 @@ func New(chain Ledger, cfg config.NeoFSBlockFetcher, logger *zap.Logger, putBloc
150
165
enqueueHeader : putHeader ,
151
166
account : account ,
152
167
stateRootInHeader : chain .GetConfig ().StateRootInHeader ,
168
+ headerSize : w .Len () + baseHeaderSize ,
153
169
shutdownCallback : shutdownCallback ,
154
170
155
171
quit : make (chan bool ),
@@ -243,32 +259,59 @@ func (bfs *Service) blockDownloader() {
243
259
for blkOid := range bfs .oidsCh {
244
260
ctx , cancel := context .WithTimeout (bfs .ctx , bfs .cfg .Timeout )
245
261
defer cancel ()
246
-
247
- rc , err := bfs .objectGet (ctx , blkOid .String ())
248
- if err != nil {
249
- if isContextCanceledErr (err ) {
262
+ var (
263
+ h * block.Header
264
+ b * block.Block
265
+ err error
266
+ rc io.ReadCloser
267
+ )
268
+
269
+ if bfs .cfg .BlocksOnly {
270
+ rc , err = bfs .objectGet (ctx , blkOid .String ())
271
+ if err != nil {
272
+ if isContextCanceledErr (err ) {
273
+ return
274
+ }
275
+ bfs .log .Error ("failed to objectGet block" , zap .String ("oid" , blkOid .String ()), zap .Error (err ))
276
+ bfs .stopService (true )
250
277
return
251
278
}
252
- bfs .log .Error ("failed to objectGet block" , zap .String ("oid" , blkOid .String ()), zap .Error (err ))
253
- bfs .stopService (true )
254
- return
255
- }
256
279
257
- b , err := bfs .readBlock (rc )
258
- if err != nil {
259
- if isContextCanceledErr (err ) {
280
+ b , err = bfs .readBlock (rc )
281
+ if err != nil {
282
+ if isContextCanceledErr (err ) {
283
+ return
284
+ }
285
+ bfs .log .Error ("failed to decode block from stream" , zap .String ("oid" , blkOid .String ()), zap .Error (err ))
286
+ bfs .stopService (true )
260
287
return
261
288
}
262
- bfs .log .Error ("failed to decode block from stream" , zap .String ("oid" , blkOid .String ()), zap .Error (err ))
263
- bfs .stopService (true )
264
- return
289
+ } else {
290
+ rc , err = bfs .objectGetRange (ctx , blkOid .String (), 0 , uint64 (bfs .headerSize ))
291
+ if err != nil {
292
+ if isContextCanceledErr (err ) {
293
+ return
294
+ }
295
+ bfs .log .Error ("failed to objectGetRange block" , zap .String ("oid" , blkOid .String ()), zap .Error (err ))
296
+ bfs .stopService (true )
297
+ return
298
+ }
299
+
300
+ h , err = bfs .readHeader (rc )
301
+ if err != nil {
302
+ if isContextCanceledErr (err ) {
303
+ return
304
+ }
305
+ bfs .log .Error ("failed to decode block from stream" , zap .String ("oid" , blkOid .String ()), zap .Error (err ))
306
+ bfs .stopService (true )
307
+ }
265
308
}
266
309
select {
267
310
case <- bfs .ctx .Done ():
268
311
return
269
312
default :
270
313
if ! bfs .cfg .BlocksOnly {
271
- err = bfs .enqueueHeader (& b . Header )
314
+ err = bfs .enqueueHeader (h )
272
315
} else {
273
316
err = bfs .enqueueBlock (b )
274
317
}
@@ -433,6 +476,15 @@ func (bfs *Service) readBlock(rc io.ReadCloser) (*block.Block, error) {
433
476
return b , r .Err
434
477
}
435
478
479
+ // readHeader decodes the header from the read closer and prepares it for adding to the blockchain.
480
+ func (bfs * Service ) readHeader (rc io.ReadCloser ) (* block.Header , error ) {
481
+ b := block .New (bfs .stateRootInHeader )
482
+ r := gio .NewBinReaderFromIO (rc )
483
+ b .Header .DecodeBinary (r )
484
+ rc .Close ()
485
+ return & b .Header , r .Err
486
+ }
487
+
436
488
// Shutdown stops the NeoFS BlockFetcher service. It prevents service from new
437
489
// block OIDs search, cancels all in-progress downloading operations and waits
438
490
// until all service routines finish their work.
@@ -555,6 +607,21 @@ func (bfs *Service) objectGet(ctx context.Context, oid string) (io.ReadCloser, e
555
607
return rc , err
556
608
}
557
609
610
+ func (bfs * Service ) objectGetRange (ctx context.Context , oid string , offset , length uint64 ) (io.ReadCloser , error ) {
611
+ rangeParam := fmt .Sprintf ("%d|%d" , offset , length )
612
+ u , err := url .Parse (fmt .Sprintf ("%s:%s/%s/%s/%s" , neofs .URIScheme , bfs .cfg .ContainerID , oid , "range" , rangeParam ))
613
+ if err != nil {
614
+ return nil , err
615
+ }
616
+
617
+ var rc io.ReadCloser
618
+ err = bfs .retry (func () error {
619
+ rc , err = neofs .GetWithClient (ctx , bfs .pool , bfs .account .PrivateKey (), u , false )
620
+ return err
621
+ })
622
+ return rc , err
623
+ }
624
+
558
625
func (bfs * Service ) objectSearch (ctx context.Context , prm client.PrmObjectSearch ) ([]oid.ID , error ) {
559
626
var (
560
627
oids []oid.ID
0 commit comments