mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-25 13:07:17 +00:00
135 lines
3.0 KiB
Go
135 lines
3.0 KiB
Go
package stateless
|
|
|
|
import (
|
|
"compress/gzip"
|
|
"fmt"
|
|
"io"
|
|
"net/url"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/ledgerwatch/turbo-geth/consensus/ethash"
|
|
"github.com/ledgerwatch/turbo-geth/core"
|
|
"github.com/ledgerwatch/turbo-geth/core/types"
|
|
"github.com/ledgerwatch/turbo-geth/core/vm"
|
|
"github.com/ledgerwatch/turbo-geth/ethdb"
|
|
"github.com/ledgerwatch/turbo-geth/params"
|
|
"github.com/ledgerwatch/turbo-geth/rlp"
|
|
)
|
|
|
|
const (
|
|
fileSchemeExportfile = "exportfile"
|
|
fileSchemeDb = "db"
|
|
)
|
|
|
|
type BlockProvider interface {
|
|
io.Closer
|
|
FastFwd(uint64) error
|
|
NextBlock() (*types.Block, error)
|
|
}
|
|
|
|
func BlockProviderForURI(uri string, createDbFunc CreateDbFunc) (BlockProvider, error) {
|
|
url, err := url.Parse(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
switch url.Scheme {
|
|
case fileSchemeExportfile:
|
|
fmt.Println("Source of blocks: export file @", url.Path)
|
|
return NewBlockProviderFromExportFile(url.Path)
|
|
case fileSchemeDb:
|
|
fallthrough
|
|
default:
|
|
fmt.Println("Source of blocks: db @", url.Path)
|
|
return NewBlockProviderFromDb(url.Path, createDbFunc)
|
|
}
|
|
}
|
|
|
|
type BlockChainBlockProvider struct {
|
|
currentBlock uint64
|
|
bc *core.BlockChain
|
|
db ethdb.Database
|
|
}
|
|
|
|
func NewBlockProviderFromDb(path string, createDbFunc CreateDbFunc) (BlockProvider, error) {
|
|
ethDb, err := createDbFunc(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
chainConfig := params.MainnetChainConfig
|
|
engine := ethash.NewFullFaker()
|
|
chain, err := core.NewBlockChain(ethDb, nil, chainConfig, engine, vm.Config{}, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &BlockChainBlockProvider{
|
|
bc: chain,
|
|
}, nil
|
|
}
|
|
|
|
func (p *BlockChainBlockProvider) Close() error {
|
|
p.db.Close()
|
|
return nil
|
|
}
|
|
|
|
func (p *BlockChainBlockProvider) FastFwd(to uint64) error {
|
|
p.currentBlock = to
|
|
return nil
|
|
}
|
|
|
|
func (p *BlockChainBlockProvider) NextBlock() (*types.Block, error) {
|
|
block := p.bc.GetBlockByNumber(p.currentBlock)
|
|
p.currentBlock++
|
|
return block, nil
|
|
}
|
|
|
|
type ExportFileBlockProvider struct {
|
|
stream *rlp.Stream
|
|
fh io.Closer
|
|
}
|
|
|
|
func NewBlockProviderFromExportFile(fn string) (BlockProvider, error) {
|
|
// Open the file handle and potentially unwrap the gzip stream
|
|
fh, err := os.Open(fn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var reader io.Reader = fh
|
|
if strings.HasSuffix(fn, ".gz") {
|
|
if reader, err = gzip.NewReader(reader); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
stream := rlp.NewStream(reader, 0)
|
|
return &ExportFileBlockProvider{stream, fh}, nil
|
|
}
|
|
|
|
func (p *ExportFileBlockProvider) Close() error {
|
|
return p.fh.Close()
|
|
}
|
|
|
|
func (p *ExportFileBlockProvider) FastFwd(to uint64) error {
|
|
var b types.Block
|
|
for {
|
|
if err := p.stream.Decode(&b); err == io.EOF {
|
|
return nil
|
|
} else if err != nil {
|
|
return fmt.Errorf("error fast fwd: %v", err)
|
|
} else if b.NumberU64() >= to-1 {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *ExportFileBlockProvider) NextBlock() (*types.Block, error) {
|
|
var b types.Block
|
|
if err := p.stream.Decode(&b); err == io.EOF {
|
|
return nil, nil
|
|
} else if err != nil {
|
|
return nil, fmt.Errorf("error fast fwd: %v", err)
|
|
}
|
|
return &b, nil
|
|
}
|