Skip to content

Commit 2112fe0

Browse files
blockfetcher: add getRange for headers processing
Signed-off-by: Ekaterina Pavlova <[email protected]>
1 parent e62e4d2 commit 2112fe0

File tree

2 files changed

+93
-21
lines changed

2 files changed

+93
-21
lines changed

pkg/core/block/block.go

+5
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ func (b *Block) GetExpectedBlockSizeWithoutTransactions(txCount int) int {
221221
return size
222222
}
223223

224+
// GetExpectedHeaderSize returns the expected header size with empty witness.
225+
func (b *Block) GetExpectedHeaderSize() int {
226+
return expectedHeaderSizeWithEmptyWitness
227+
}
228+
224229
// ToStackItem converts Block to stackitem.Item.
225230
func (b *Block) ToStackItem() stackitem.Item {
226231
items := []stackitem.Item{

pkg/services/blockfetcher/blockfetcher.go

+88-21
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ import (
1414

1515
"github.com/nspcc-dev/neo-go/pkg/config"
1616
"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"
1719
gio "github.com/nspcc-dev/neo-go/pkg/io"
1820
"github.com/nspcc-dev/neo-go/pkg/services/helpers/neofs"
21+
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
1922
"github.com/nspcc-dev/neo-go/pkg/wallet"
2023
"github.com/nspcc-dev/neofs-sdk-go/client"
2124
"github.com/nspcc-dev/neofs-sdk-go/container"
@@ -59,12 +62,12 @@ type Service struct {
5962
log *zap.Logger
6063
cfg config.NeoFSBlockFetcher
6164
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
6871

6972
oidsCh chan oid.ID
7073
// wg is a wait group for block downloaders.
@@ -140,6 +143,18 @@ func New(chain Ledger, cfg config.NeoFSBlockFetcher, logger *zap.Logger, putBloc
140143
if err != nil {
141144
return nil, err
142145
}
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)
143158
return &Service{
144159
chain: chain,
145160
pool: poolWrapper{Pool: p},
@@ -150,6 +165,7 @@ func New(chain Ledger, cfg config.NeoFSBlockFetcher, logger *zap.Logger, putBloc
150165
enqueueHeader: putHeader,
151166
account: account,
152167
stateRootInHeader: chain.GetConfig().StateRootInHeader,
168+
headerSize: w.Len() + baseHeaderSize,
153169
shutdownCallback: shutdownCallback,
154170

155171
quit: make(chan bool),
@@ -243,32 +259,59 @@ func (bfs *Service) blockDownloader() {
243259
for blkOid := range bfs.oidsCh {
244260
ctx, cancel := context.WithTimeout(bfs.ctx, bfs.cfg.Timeout)
245261
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)
250277
return
251278
}
252-
bfs.log.Error("failed to objectGet block", zap.String("oid", blkOid.String()), zap.Error(err))
253-
bfs.stopService(true)
254-
return
255-
}
256279

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)
260287
return
261288
}
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+
}
265308
}
266309
select {
267310
case <-bfs.ctx.Done():
268311
return
269312
default:
270313
if !bfs.cfg.BlocksOnly {
271-
err = bfs.enqueueHeader(&b.Header)
314+
err = bfs.enqueueHeader(h)
272315
} else {
273316
err = bfs.enqueueBlock(b)
274317
}
@@ -433,6 +476,15 @@ func (bfs *Service) readBlock(rc io.ReadCloser) (*block.Block, error) {
433476
return b, r.Err
434477
}
435478

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+
436488
// Shutdown stops the NeoFS BlockFetcher service. It prevents service from new
437489
// block OIDs search, cancels all in-progress downloading operations and waits
438490
// until all service routines finish their work.
@@ -555,6 +607,21 @@ func (bfs *Service) objectGet(ctx context.Context, oid string) (io.ReadCloser, e
555607
return rc, err
556608
}
557609

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+
558625
func (bfs *Service) objectSearch(ctx context.Context, prm client.PrmObjectSearch) ([]oid.ID, error) {
559626
var (
560627
oids []oid.ID

0 commit comments

Comments
 (0)