Skip to content

Commit

Permalink
fix: Generate t_aux for snap when not present (#143)
Browse files Browse the repository at this point in the history
  • Loading branch information
magik6k committed Aug 12, 2024
1 parent d0f7b50 commit 9045e34
Show file tree
Hide file tree
Showing 6 changed files with 355 additions and 6 deletions.
5 changes: 5 additions & 0 deletions lib/ffi/snap_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/filecoin-project/curio/lib/asyncwrite"
"github.com/filecoin-project/curio/lib/ffiselect"
paths2 "github.com/filecoin-project/curio/lib/paths"
"github.com/filecoin-project/curio/lib/proof"
"github.com/filecoin-project/curio/lib/tarutil"

"github.com/filecoin-project/lotus/storage/sealer/fr32"
Expand Down Expand Up @@ -185,6 +186,10 @@ func (sb *SealCalls) EncodeUpdate(
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("extracting cache: %w", err)
}

if err := proof.EnsureTauxForType(sector.ProofType, keyCachePath); err != nil {
return cid.Cid{}, cid.Cid{}, xerrors.Errorf("ensuring t_aux exists: %w", err)
}
}

// allocate update file
Expand Down
42 changes: 42 additions & 0 deletions lib/proof/bincode_util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package proof

import (
"encoding/binary"
"io"

"golang.org/x/xerrors"
)

func ReadLE[T any](r io.Reader) (T, error) {
var out T
err := binary.Read(r, binary.LittleEndian, &out)
return out, err
}

func ReadString(r io.Reader) (string, error) {
l, err := ReadLE[uint64](r)
if err != nil {
return "", xerrors.Errorf("failed to read string length: %w", err)
}

buf := make([]byte, l)
if _, err := io.ReadFull(r, buf); err != nil {
return "", xerrors.Errorf("failed to read string: %w", err)
}

return string(buf), nil
}

func WriteLE[T any](w io.Writer, data T) error {
return binary.Write(w, binary.LittleEndian, data)
}

func WriteString(w io.Writer, s string) error {
if err := WriteLE(w, uint64(len(s))); err != nil {
return xerrors.Errorf("failed to write string length: %w", err)
}
if _, err := w.Write([]byte(s)); err != nil {
return xerrors.Errorf("failed to write string: %w", err)
}
return nil
}
6 changes: 0 additions & 6 deletions lib/proof/porep_vproof_bin_decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ import (
// This is the format output by the C++ supraseal C1 implementation.
// bincode - https://github.com/bincode-org/bincode

func ReadLE[T any](r io.Reader) (T, error) {
var out T
err := binary.Read(r, binary.LittleEndian, &out)
return out, err
}

func DecodeCommit1OutRaw(r io.Reader) (Commit1OutRaw, error) {
var out Commit1OutRaw
var err error
Expand Down
84 changes: 84 additions & 0 deletions lib/proof/t_aux_gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package proof

import (
"bytes"
"fmt"
"os"
"path/filepath"

"golang.org/x/xerrors"

"github.com/filecoin-project/go-state-types/abi"
)

var tauxName = "t_aux"

// EnsureTauxForType ensures that the t_aux file exists in the specified path for the specified seal proof type.
// If the file does not exist, it will be created with the default values for the specified seal proof type.
func EnsureTauxForType(spt abi.RegisteredSealProof, path string) error {
// check if the file exists
auxPath := filepath.Join(path, tauxName)
if _, err := os.Stat(auxPath); !os.IsNotExist(err) {
return nil // file exists, nothing to do
}

// no t_aux, create one that will satisfy rust-fil-proofs

if spt != abi.RegisteredSealProof_StackedDrg32GiBV1_1 && spt != abi.RegisteredSealProof_StackedDrg32GiBV1_1_Feat_SyntheticPoRep {
return xerrors.Errorf("unsupported seal proof type: %v", spt)
}

treeRRowsToDiscard := uint64(2)
if envset := os.Getenv("FIL_PROOFS_ROWS_TO_DISCARD"); envset != "" {
_, err := fmt.Sscan(envset, &treeRRowsToDiscard)
if err != nil {
return xerrors.Errorf("failed to parse FIL_PROOFS_ROWS_TO_DISCARD: %w", err)
}
}

taux := TemporaryAux{
Labels: TAuxLabels{},
TreeDConfig: StoreConfig{
Path: path,
ID: "tree-d",
Size: iptr(2147483647),
RowsToDiscard: 0,
},
TreeRConfig: StoreConfig{
Path: path,
ID: "tree-r-last",
Size: iptr(153391689),
RowsToDiscard: treeRRowsToDiscard,
},
TreeCConfig: StoreConfig{
Path: path,
ID: "tree-c",
Size: iptr(153391689),
RowsToDiscard: 0,
},
}

for i := 0; i < 11; i++ {
taux.Labels.Labels = append(taux.Labels.Labels, StoreConfig{
Path: path,
ID: fmt.Sprintf("layer-%d", i+1),
Size: iptr(1073741824),
RowsToDiscard: 0,
})
}

var buf bytes.Buffer
if err := EncodeTAux(&buf, taux); err != nil {
return xerrors.Errorf("failed to encode taux: %w", err)
}

if err := os.WriteFile(auxPath, buf.Bytes(), 0644); err != nil {
return xerrors.Errorf("failed to write taux file: %w", err)
}

return nil
}

func iptr(i uint64) *uint64 {
return &i
}
48 changes: 48 additions & 0 deletions lib/proof/t_aux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package proof

import (
"bytes"
"encoding/base64"
"encoding/json"
"testing"

"github.com/snadrus/must"
"github.com/stretchr/testify/require"
)

const TAuxGolden = `CwAAAAAAAAAhAAAAAAAAAC9kYXRhLzEvc3RvcmUvY2FjaGUvcy10MDI2MjAtMjAxMAcAAAAAAAAA
bGF5ZXItMQEAAABAAAAAAAAAAAAAAAAAIQAAAAAAAAAvZGF0YS8xL3N0b3JlL2NhY2hlL3MtdDAy
NjIwLTIwMTAHAAAAAAAAAGxheWVyLTIBAAAAQAAAAAAAAAAAAAAAACEAAAAAAAAAL2RhdGEvMS9z
dG9yZS9jYWNoZS9zLXQwMjYyMC0yMDEwBwAAAAAAAABsYXllci0zAQAAAEAAAAAAAAAAAAAAAAAh
AAAAAAAAAC9kYXRhLzEvc3RvcmUvY2FjaGUvcy10MDI2MjAtMjAxMAcAAAAAAAAAbGF5ZXItNAEA
AABAAAAAAAAAAAAAAAAAIQAAAAAAAAAvZGF0YS8xL3N0b3JlL2NhY2hlL3MtdDAyNjIwLTIwMTAH
AAAAAAAAAGxheWVyLTUBAAAAQAAAAAAAAAAAAAAAACEAAAAAAAAAL2RhdGEvMS9zdG9yZS9jYWNo
ZS9zLXQwMjYyMC0yMDEwBwAAAAAAAABsYXllci02AQAAAEAAAAAAAAAAAAAAAAAhAAAAAAAAAC9k
YXRhLzEvc3RvcmUvY2FjaGUvcy10MDI2MjAtMjAxMAcAAAAAAAAAbGF5ZXItNwEAAABAAAAAAAAA
AAAAAAAAIQAAAAAAAAAvZGF0YS8xL3N0b3JlL2NhY2hlL3MtdDAyNjIwLTIwMTAHAAAAAAAAAGxh
eWVyLTgBAAAAQAAAAAAAAAAAAAAAACEAAAAAAAAAL2RhdGEvMS9zdG9yZS9jYWNoZS9zLXQwMjYy
MC0yMDEwBwAAAAAAAABsYXllci05AQAAAEAAAAAAAAAAAAAAAAAhAAAAAAAAAC9kYXRhLzEvc3Rv
cmUvY2FjaGUvcy10MDI2MjAtMjAxMAgAAAAAAAAAbGF5ZXItMTABAAAAQAAAAAAAAAAAAAAAACEA
AAAAAAAAL2RhdGEvMS9zdG9yZS9jYWNoZS9zLXQwMjYyMC0yMDEwCAAAAAAAAABsYXllci0xMQEA
AABAAAAAAAAAAAAAAAAAIQAAAAAAAAAvZGF0YS8xL3N0b3JlL2NhY2hlL3MtdDAyNjIwLTIwMTAG
AAAAAAAAAHRyZWUtZAH///9/AAAAAAAAAAAAAAAAIQAAAAAAAAAvZGF0YS8xL3N0b3JlL2NhY2hl
L3MtdDAyNjIwLTIwMTALAAAAAAAAAHRyZWUtci1sYXN0AUmSJAkAAAAAAgAAAAAAAAAhAAAAAAAA
AC9kYXRhLzEvc3RvcmUvY2FjaGUvcy10MDI2MjAtMjAxMAYAAAAAAAAAdHJlZS1jAUmSJAkAAAAA
AAAAAAAAAAA=`

func TestTAuxRoundtrip(t *testing.T) {
gbytes := must.One(base64.StdEncoding.DecodeString(TAuxGolden))

dec, err := DecodeTAux(bytes.NewReader(gbytes))
require.NoError(t, err)

// print as json
enc, err := json.MarshalIndent(dec, "", " ")
require.NoError(t, err)
t.Log(string(enc))

var reenc bytes.Buffer
require.NoError(t, EncodeTAux(&reenc, *dec))

require.Equal(t, gbytes, reenc.Bytes())
}
176 changes: 176 additions & 0 deletions lib/proof/t_aux_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package proof

import (
"io"

"golang.org/x/xerrors"
)

type StoreConfig struct {
// A directory in which data (a merkle tree) can be persisted.
Path string

// A unique identifier used to help specify the on-disk store location for this particular data.
ID string

// The number of elements in the DiskStore. This field is optional, and unused internally.
Size *uint64

// The number of merkle tree rows_to_discard then cache on disk.
RowsToDiscard uint64
}

type TAuxLabels struct {
Labels []StoreConfig
}

type TemporaryAux struct {
Labels TAuxLabels
TreeDConfig StoreConfig
TreeRConfig StoreConfig
TreeCConfig StoreConfig
}

func DecodeStoreConfig(r io.Reader) (StoreConfig, error) {
var sc StoreConfig
var err error

sc.Path, err = ReadString(r)
if err != nil {
return StoreConfig{}, xerrors.Errorf("failed to decode path: %w", err)
}

sc.ID, err = ReadString(r)
if err != nil {
return StoreConfig{}, xerrors.Errorf("failed to decode ID: %w", err)
}

// Size in an option, so prefixed with a 0x01 byte if present or 0x00 if not.
var b [1]byte
if _, err := io.ReadFull(r, b[:]); err != nil {
return StoreConfig{}, xerrors.Errorf("failed to read size present byte: %w", err)
}
if b[0] == 0x01 {
size, err := ReadLE[uint64](r)
if err != nil {
return StoreConfig{}, xerrors.Errorf("failed to read size: %w", err)
}
sc.Size = &size
}

sc.RowsToDiscard, err = ReadLE[uint64](r)
if err != nil {
return StoreConfig{}, xerrors.Errorf("failed to read rows to discard: %w", err)
}

return sc, nil
}

func DecodeLabels(r io.Reader) (*TAuxLabels, error) {
numLabels, err := ReadLE[uint64](r)
if err != nil {
return nil, xerrors.Errorf("failed to read number of labels: %w", err)
}

labels := make([]StoreConfig, numLabels)
for i := range labels {
labels[i], err = DecodeStoreConfig(r)
if err != nil {
return nil, xerrors.Errorf("failed to decode label %d: %w", i, err)
}
}

return &TAuxLabels{Labels: labels}, nil
}

func DecodeTAux(r io.Reader) (*TemporaryAux, error) {
labels, err := DecodeLabels(r)
if err != nil {
return nil, xerrors.Errorf("failed to decode labels: %w", err)
}

treeDConfig, err := DecodeStoreConfig(r)
if err != nil {
return nil, xerrors.Errorf("failed to decode treeDConfig: %w", err)
}

treeRConfig, err := DecodeStoreConfig(r)
if err != nil {
return nil, xerrors.Errorf("failed to decode treeRConfig: %w", err)
}

treeCConfig, err := DecodeStoreConfig(r)
if err != nil {
return nil, xerrors.Errorf("failed to decode treeCConfig: %w", err)
}

return &TemporaryAux{
Labels: *labels,
TreeDConfig: treeDConfig,
TreeRConfig: treeRConfig,
TreeCConfig: treeCConfig,
}, nil
}

func EncodeStoreConfig(w io.Writer, sc StoreConfig) error {
if err := WriteString(w, sc.Path); err != nil {
return xerrors.Errorf("failed to encode path: %w", err)
}

if err := WriteString(w, sc.ID); err != nil {
return xerrors.Errorf("failed to encode ID: %w", err)
}

if sc.Size != nil {
if _, err := w.Write([]byte{0x01}); err != nil {
return xerrors.Errorf("failed to write size present byte: %w", err)
}
if err := WriteLE(w, *sc.Size); err != nil {
return xerrors.Errorf("failed to write size: %w", err)
}
} else {
if _, err := w.Write([]byte{0x00}); err != nil {
return xerrors.Errorf("failed to write size absent byte: %w", err)
}
}

if err := WriteLE(w, sc.RowsToDiscard); err != nil {
return xerrors.Errorf("failed to write rows to discard: %w", err)
}

return nil
}

func EncodeLabels(w io.Writer, labels TAuxLabels) error {
if err := WriteLE(w, uint64(len(labels.Labels))); err != nil {
return xerrors.Errorf("failed to write number of labels: %w", err)
}

for i, label := range labels.Labels {
if err := EncodeStoreConfig(w, label); err != nil {
return xerrors.Errorf("failed to encode label %d: %w", i, err)
}
}

return nil
}

func EncodeTAux(w io.Writer, taux TemporaryAux) error {
if err := EncodeLabels(w, taux.Labels); err != nil {
return xerrors.Errorf("failed to encode labels: %w", err)
}

if err := EncodeStoreConfig(w, taux.TreeDConfig); err != nil {
return xerrors.Errorf("failed to encode treeDConfig: %w", err)
}

if err := EncodeStoreConfig(w, taux.TreeRConfig); err != nil {
return xerrors.Errorf("failed to encode treeRConfig: %w", err)
}

if err := EncodeStoreConfig(w, taux.TreeCConfig); err != nil {
return xerrors.Errorf("failed to encode treeCConfig: %w", err)
}

return nil
}

0 comments on commit 9045e34

Please sign in to comment.