lotus/node/bundle/manifest.go
2022-05-26 17:30:32 -04:00

137 lines
3.7 KiB
Go

package bundle
import (
"bytes"
"context"
"fmt"
"io"
"os"
"github.com/ipld/go-car"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/mitchellh/go-homedir"
)
func FetchAndLoadBundleFromRelease(ctx context.Context, basePath string, bs blockstore.Blockstore, av actors.Version, rel, netw string) (cid.Cid, error) {
fetcher, err := NewBundleFetcher(basePath)
if err != nil {
return cid.Undef, xerrors.Errorf("error creating fetcher for builtin-actors version %d: %w", av, err)
}
path, err := fetcher.FetchFromRelease(int(av), rel, netw)
if err != nil {
return cid.Undef, xerrors.Errorf("error fetching bundle for builtin-actors version %d: %w", av, err)
}
return LoadBundle(ctx, bs, path, av)
}
func FetchAndLoadBundleFromURL(ctx context.Context, basePath string, bs blockstore.Blockstore, av actors.Version, rel, netw, url, cksum string) (cid.Cid, error) {
fetcher, err := NewBundleFetcher(basePath)
if err != nil {
return cid.Undef, xerrors.Errorf("error creating fetcher for builtin-actors version %d: %w", av, err)
}
path, err := fetcher.FetchFromURL(int(av), rel, netw, url, cksum)
if err != nil {
return cid.Undef, xerrors.Errorf("error fetching bundle for builtin-actors version %d: %w", av, err)
}
return LoadBundle(ctx, bs, path, av)
}
func LoadBundle(ctx context.Context, bs blockstore.Blockstore, path string, av actors.Version) (cid.Cid, error) {
f, err := os.Open(path)
if err != nil {
return cid.Undef, xerrors.Errorf("error opening bundle for builtin-actors version %d: %w", av, err)
}
defer f.Close() //nolint
data, err := io.ReadAll(f)
if err != nil {
return cid.Undef, xerrors.Errorf("error reading bundle for builtin-actors version %d: %w", av, err)
}
blobr := bytes.NewReader(data)
hdr, err := car.LoadCar(ctx, bs, blobr)
if err != nil {
return cid.Undef, xerrors.Errorf("error loading builtin actors v%d bundle: %w", av, err)
}
// TODO: check that this only has one root?
manifestCid := hdr.Roots[0]
if val, ok := build.ActorsCIDs[av]; ok {
if val != manifestCid {
return cid.Undef, xerrors.Errorf("actors V%d manifest CID %s did not match CID given in params file: %s", av, manifestCid, val)
}
}
actors.AddManifest(av, manifestCid)
mfCid, ok := actors.GetManifest(av)
if !ok {
return cid.Undef, xerrors.Errorf("missing manifest CID for builtin-actors vrsion %d", av)
}
return mfCid, nil
}
// utility for blanket loading outside DI
func FetchAndLoadBundles(ctx context.Context, bs blockstore.Blockstore, bar map[actors.Version]build.Bundle) error {
netw := build.NetworkBundle
path := os.Getenv("LOTUS_PATH")
if path == "" {
var err error
path, err = homedir.Expand("~/.lotus")
if err != nil {
return err
}
}
for av, bd := range bar {
envvar := fmt.Sprintf("LOTUS_BUILTIN_ACTORS_V%d_BUNDLE", av)
switch {
case os.Getenv(envvar) != "":
// this is a local bundle, specified by an env var to load from the filesystem
path := os.Getenv(envvar)
if _, err := LoadBundle(ctx, bs, path, av); err != nil {
return err
}
case bd.Path[netw] != "":
if _, err := LoadBundle(ctx, bs, bd.Path[netw], av); err != nil {
return err
}
case bd.URL[netw].URL != "":
if _, err := FetchAndLoadBundleFromURL(ctx, path, bs, av, bd.Release, netw, bd.URL[netw].URL, bd.URL[netw].Checksum); err != nil {
return err
}
case bd.Release != "":
if _, err := FetchAndLoadBundleFromRelease(ctx, path, bs, av, bd.Release, netw); err != nil {
return err
}
}
}
cborStore := cbor.NewCborStore(bs)
if err := actors.LoadManifests(ctx, cborStore); err != nil {
return err
}
return nil
}