github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/chaindump/dump.go (about)

     1  package chaindump
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/nspcc-dev/neo-go/pkg/config"
     7  	"github.com/nspcc-dev/neo-go/pkg/core/block"
     8  	"github.com/nspcc-dev/neo-go/pkg/io"
     9  	"github.com/nspcc-dev/neo-go/pkg/util"
    10  )
    11  
    12  // DumperRestorer is an interface to get/add blocks from/to.
    13  type DumperRestorer interface {
    14  	AddBlock(block *block.Block) error
    15  	GetBlock(hash util.Uint256) (*block.Block, error)
    16  	GetConfig() config.Blockchain
    17  	GetHeaderHash(uint32) util.Uint256
    18  }
    19  
    20  // Dump writes count blocks from start to the provided writer.
    21  // Note: header needs to be written separately by a client.
    22  func Dump(bc DumperRestorer, w *io.BinWriter, start, count uint32) error {
    23  	for i := start; i < start+count; i++ {
    24  		bh := bc.GetHeaderHash(i)
    25  		b, err := bc.GetBlock(bh)
    26  		if err != nil {
    27  			return err
    28  		}
    29  		buf := io.NewBufBinWriter()
    30  		b.EncodeBinary(buf.BinWriter)
    31  		bytes := buf.Bytes()
    32  		w.WriteU32LE(uint32(len(bytes)))
    33  		w.WriteBytes(bytes)
    34  		if w.Err != nil {
    35  			return w.Err
    36  		}
    37  	}
    38  	return nil
    39  }
    40  
    41  // Restore restores blocks from the provided reader.
    42  // f is called after addition of every block.
    43  func Restore(bc DumperRestorer, r *io.BinReader, skip, count uint32, f func(b *block.Block) error) error {
    44  	readBlock := func(r *io.BinReader) ([]byte, error) {
    45  		var size = r.ReadU32LE()
    46  		buf := make([]byte, size)
    47  		r.ReadBytes(buf)
    48  		return buf, r.Err
    49  	}
    50  
    51  	i := uint32(0)
    52  	for ; i < skip; i++ {
    53  		_, err := readBlock(r)
    54  		if err != nil {
    55  			return err
    56  		}
    57  	}
    58  
    59  	stateRootInHeader := bc.GetConfig().StateRootInHeader
    60  
    61  	for ; i < skip+count; i++ {
    62  		buf, err := readBlock(r)
    63  		if err != nil {
    64  			return err
    65  		}
    66  		b := block.New(stateRootInHeader)
    67  		r := io.NewBinReaderFromBuf(buf)
    68  		b.DecodeBinary(r)
    69  		if r.Err != nil {
    70  			return r.Err
    71  		}
    72  		if b.Index != 0 || i != 0 || skip != 0 {
    73  			err = bc.AddBlock(b)
    74  			if err != nil {
    75  				return fmt.Errorf("failed to add block %d: %w", i, err)
    76  			}
    77  		}
    78  		if f != nil {
    79  			if err := f(b); err != nil {
    80  				return err
    81  			}
    82  		}
    83  	}
    84  	return nil
    85  }