3795cc2bd2
This paves the way for better object lifetime management. Concretely, it makes it possible to: - have different stores backing chain and state data. - having the same datastore library, but using different parameters. - attach different caching layers/policies to each class of data, e.g. sizing caches differently. - specifying different retention policies for chain and state data. This separation is important because: - access patterns/frequency of chain and state data are different. - state is derivable from chain, so one could never expunge the chain store, and only retain state objects reachable from the last finality in the state store.
74 lines
2.1 KiB
Go
74 lines
2.1 KiB
Go
package modules
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
|
|
"github.com/ipfs/go-datastore"
|
|
"github.com/ipld/go-car"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/filecoin-project/lotus/chain/store"
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
|
)
|
|
|
|
func ErrorGenesis() Genesis {
|
|
return func() (header *types.BlockHeader, e error) {
|
|
return nil, xerrors.New("No genesis block provided, provide the file with 'lotus daemon --genesis=[genesis file]'")
|
|
}
|
|
}
|
|
|
|
func LoadGenesis(genBytes []byte) func(dtypes.ChainBlockstore) Genesis {
|
|
return func(bs dtypes.ChainBlockstore) Genesis {
|
|
return func() (header *types.BlockHeader, e error) {
|
|
c, err := car.LoadCar(bs, bytes.NewReader(genBytes))
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("loading genesis car file failed: %w", err)
|
|
}
|
|
if len(c.Roots) != 1 {
|
|
return nil, xerrors.New("expected genesis file to have one root")
|
|
}
|
|
root, err := bs.Get(c.Roots[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
h, err := types.DecodeBlock(root.RawData())
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("decoding block failed: %w", err)
|
|
}
|
|
return h, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func DoSetGenesis(_ dtypes.AfterGenesisSet) {}
|
|
|
|
func SetGenesis(cs *store.ChainStore, g Genesis) (dtypes.AfterGenesisSet, error) {
|
|
genFromRepo, err := cs.GetGenesis()
|
|
if err == nil {
|
|
if os.Getenv("LOTUS_SKIP_GENESIS_CHECK") != "_yes_" {
|
|
expectedGenesis, err := g()
|
|
if err != nil {
|
|
return dtypes.AfterGenesisSet{}, xerrors.Errorf("getting expected genesis failed: %w", err)
|
|
}
|
|
|
|
if genFromRepo.Cid() != expectedGenesis.Cid() {
|
|
return dtypes.AfterGenesisSet{}, xerrors.Errorf("genesis in the repo is not the one expected by this version of Lotus!")
|
|
}
|
|
}
|
|
return dtypes.AfterGenesisSet{}, nil // already set, noop
|
|
}
|
|
if err != datastore.ErrNotFound {
|
|
return dtypes.AfterGenesisSet{}, xerrors.Errorf("getting genesis block failed: %w", err)
|
|
}
|
|
|
|
genesis, err := g()
|
|
if err != nil {
|
|
return dtypes.AfterGenesisSet{}, xerrors.Errorf("genesis func failed: %w", err)
|
|
}
|
|
|
|
return dtypes.AfterGenesisSet{}, cs.SetGenesis(genesis)
|
|
}
|