Skip to content

Commit

Permalink
Add tests to sanity-check embedded built-in actors metadata (filecoin…
Browse files Browse the repository at this point in the history
…-project#11684)

Add tests that assert the embedded built-in actors metadata is correct:

* the corresponding CAR file is present in built-in actors released
  assets as a CAR file.
* manifest CID is the only root CID in the corresponding CAR file.
* actor CIDs are present in the corresponding CAR file.

Fixes filecoin-project#11683
  • Loading branch information
masih authored Mar 6, 2024
1 parent 40f3071 commit 1d4f539
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/builtin-actor-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Built-in Actors
on:
push:
paths:
- build/actors
- build/builtin_actors_gen.go
branches:
- release/*
jobs:
release:
name: Release Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.21
- run: go test -tags=release ./build
107 changes: 107 additions & 0 deletions build/builtin_actors_gen_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//go:build release
// +build release

package build_test

import (
"archive/tar"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io"
"net/http"
"os"
"strings"
"testing"

"github.com/DataDog/zstd"
"github.com/ipfs/go-cid"
"github.com/ipld/go-car/v2"
"github.com/stretchr/testify/require"

actorstypes "github.com/filecoin-project/go-state-types/actors"

"github.com/filecoin-project/lotus/build"
)

func TestEmbeddedBuiltinActorsMetadata(t *testing.T) {
subjectsByVersionByNetworks := make(map[actorstypes.Version]map[string]*build.BuiltinActorsMetadata)
for _, subject := range build.EmbeddedBuiltinActorsMetadata {
if subject.BundleGitTag == "" {
// BundleGitTag is required to verify the SHA-256 checksum.
// The pack script only includes this for the latest network version, and it is good enough to only
// check the latest network version metadata. Hence the skip.
continue
}
v, ok := subjectsByVersionByNetworks[subject.Version]
if !ok {
v = make(map[string]*build.BuiltinActorsMetadata)
}
v[subject.Network] = subject
subjectsByVersionByNetworks[subject.Version] = v
}

for version, networks := range subjectsByVersionByNetworks {
cachedCar, err := os.Open(fmt.Sprintf("./actors/v%v.tar.zst", version))
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, cachedCar.Close()) })
tarReader := tar.NewReader(zstd.NewReader(cachedCar))
for {
header, err := tarReader.Next()
if errors.Is(err, io.EOF) {
break
}
require.NoError(t, err)

network := strings.TrimSuffix(strings.TrimPrefix(header.Name, "builtin-actors-"), ".car")
subject, found := networks[network]
if !found {
continue
}

shaURL := fmt.Sprintf("https://github.com/filecoin-project/builtin-actors/releases/download/%s/builtin-actors-%s.sha256", subject.BundleGitTag, subject.Network)
resp, err := http.Get(shaURL)
require.NoError(t, err, "failed to retrieve CAR SHA")
require.Equal(t, http.StatusOK, resp.StatusCode, "unexpected response status code while retrieving CAR SHA")

respBody, err := io.ReadAll(resp.Body)
require.NoError(t, resp.Body.Close())
require.NoError(t, err)
fields := strings.Fields(string(respBody))
require.Len(t, fields, 2)
wantShaHex := fields[0]

hasher := sha256.New()
reader, err := car.NewBlockReader(io.TeeReader(tarReader, hasher))
require.NoError(t, err)

require.EqualValues(t, 1, reader.Version)
require.Len(t, reader.Roots, 1, "expected exactly one root CID for builtin actors bundle network %s, version %v", subject.Network, subject.Version)
require.True(t, reader.Roots[0].Equals(subject.ManifestCid), "manifest CID does not match")

subjectActorsByCid := make(map[cid.Cid]string)
for name, c := range subject.Actors {
subjectActorsByCid[c] = name
}
for {
next, err := reader.Next()
if errors.Is(err, io.EOF) {
break
}
require.NoError(t, err)
name, found := subjectActorsByCid[next.Cid()]
if found {
t.Logf("OK: %sv%v/%s -> %s", subject.Network, subject.Version, name, next.Cid())
delete(subjectActorsByCid, next.Cid())
}
}
require.Empty(t, subjectActorsByCid, "ZST CAR bundle did not contain CIDs for all actors; missing: %v", subjectActorsByCid)

gotShaHex := hex.EncodeToString(hasher.Sum(nil))
require.Equal(t, wantShaHex, gotShaHex, "SHA-256 digest of ZST CAR bundle does not match builtin-actors release")
delete(networks, network)
}
require.Empty(t, networks, "CAR bundle did not contain CIDs for network; missing: %v", networks)
}
}

0 comments on commit 1d4f539

Please sign in to comment.