2020-11-24 08:36:09 +00:00
|
|
|
package chaindump
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2022-01-13 00:19:10 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
2020-11-24 08:36:09 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
2022-01-13 00:19:10 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
2020-11-24 08:36:09 +00:00
|
|
|
)
|
|
|
|
|
2022-04-20 18:30:09 +00:00
|
|
|
// DumperRestorer is an interface to get/add blocks from/to.
|
2022-01-13 00:19:10 +00:00
|
|
|
type DumperRestorer interface {
|
|
|
|
AddBlock(block *block.Block) error
|
|
|
|
GetBlock(hash util.Uint256) (*block.Block, error)
|
|
|
|
GetConfig() config.ProtocolConfiguration
|
2022-11-18 20:19:50 +00:00
|
|
|
GetHeaderHash(uint32) util.Uint256
|
2022-01-13 00:19:10 +00:00
|
|
|
}
|
|
|
|
|
2020-11-24 08:36:09 +00:00
|
|
|
// Dump writes count blocks from start to the provided writer.
|
2022-04-20 18:30:09 +00:00
|
|
|
// Note: header needs to be written separately by a client.
|
2022-01-13 00:19:10 +00:00
|
|
|
func Dump(bc DumperRestorer, w *io.BinWriter, start, count uint32) error {
|
2020-11-24 08:36:09 +00:00
|
|
|
for i := start; i < start+count; i++ {
|
2022-11-18 20:19:50 +00:00
|
|
|
bh := bc.GetHeaderHash(i)
|
2020-11-24 08:36:09 +00:00
|
|
|
b, err := bc.GetBlock(bh)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
buf := io.NewBufBinWriter()
|
|
|
|
b.EncodeBinary(buf.BinWriter)
|
|
|
|
bytes := buf.Bytes()
|
|
|
|
w.WriteU32LE(uint32(len(bytes)))
|
|
|
|
w.WriteBytes(bytes)
|
|
|
|
if w.Err != nil {
|
|
|
|
return w.Err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-04-20 18:30:09 +00:00
|
|
|
// Restore restores blocks from the provided reader.
|
2020-11-24 08:36:09 +00:00
|
|
|
// f is called after addition of every block.
|
2022-01-13 00:19:10 +00:00
|
|
|
func Restore(bc DumperRestorer, r *io.BinReader, skip, count uint32, f func(b *block.Block) error) error {
|
2020-11-24 08:36:09 +00:00
|
|
|
readBlock := func(r *io.BinReader) ([]byte, error) {
|
|
|
|
var size = r.ReadU32LE()
|
|
|
|
buf := make([]byte, size)
|
|
|
|
r.ReadBytes(buf)
|
|
|
|
return buf, r.Err
|
|
|
|
}
|
|
|
|
|
|
|
|
i := uint32(0)
|
|
|
|
for ; i < skip; i++ {
|
|
|
|
_, err := readBlock(r)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stateRootInHeader := bc.GetConfig().StateRootInHeader
|
|
|
|
|
|
|
|
for ; i < skip+count; i++ {
|
|
|
|
buf, err := readBlock(r)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-03-25 18:46:52 +00:00
|
|
|
b := block.New(stateRootInHeader)
|
2020-11-24 08:36:09 +00:00
|
|
|
r := io.NewBinReaderFromBuf(buf)
|
|
|
|
b.DecodeBinary(r)
|
|
|
|
if r.Err != nil {
|
|
|
|
return r.Err
|
|
|
|
}
|
|
|
|
if b.Index != 0 || i != 0 || skip != 0 {
|
|
|
|
err = bc.AddBlock(b)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to add block %d: %w", i, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if f != nil {
|
|
|
|
if err := f(b); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|