-
Notifications
You must be signed in to change notification settings - Fork 30
/
commp.go
101 lines (90 loc) · 3.04 KB
/
commp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package graphsplit
import (
"bufio"
"context"
"fmt"
"io"
"os"
"path"
"github.com/filecoin-project/go-commp-utils/ffiwrapper"
"github.com/filecoin-project/go-padreader"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filedrive-team/filehelper/carv1"
"github.com/ipfs/go-cid"
"github.com/ipld/go-car"
"golang.org/x/xerrors"
)
type CommPRet struct {
Root cid.Cid
PayloadSize int64
Size abi.UnpaddedPieceSize
}
// almost copy paste from https://github.com/filecoin-project/lotus/node/impl/client/client.go#L749-L770
func CalcCommP(ctx context.Context, inpath string, rename, addPadding bool) (*CommPRet, error) {
dir, _ := path.Split(inpath)
// Hard-code the sector type to 32GiBV1_1, because:
// - ffiwrapper.GeneratePieceCIDFromFile requires a RegisteredSealProof
// - commP itself is sector-size independent, with rather low probability of that changing
// ( note how the final rust call is identical for every RegSP type )
// https://github.com/filecoin-project/rust-filecoin-proofs-api/blob/v5.0.0/src/seal.rs#L1040-L1050
//
// IF/WHEN this changes in the future we will have to be able to calculate
// "old style" commP, and thus will need to introduce a version switch or similar
arbitraryProofType := abi.RegisteredSealProof_StackedDrg32GiBV1_1
st, err := os.Stat(inpath)
if err != nil {
return nil, err
}
if st.IsDir() {
return nil, fmt.Errorf("path %s is dir", inpath)
}
payloadSize := st.Size()
rdr, err := os.OpenFile(inpath, os.O_RDWR, 0644)
if err != nil {
return nil, err
}
defer rdr.Close() //nolint:errcheck
stat, err := rdr.Stat()
if err != nil {
return nil, err
}
carSize := stat.Size()
// check that the data is a car file; if it's not, retrieval won't work
_, err = car.ReadHeader(bufio.NewReader(rdr))
if err != nil {
return nil, xerrors.Errorf("not a car file: %w", err)
}
if _, err := rdr.Seek(0, io.SeekStart); err != nil {
return nil, xerrors.Errorf("seek to start: %w", err)
}
pieceReader, pieceSize := padreader.New(rdr, uint64(carSize))
commP, err := ffiwrapper.GeneratePieceCIDFromFile(arbitraryProofType, pieceReader, pieceSize)
if err != nil {
return nil, xerrors.Errorf("computing commP failed: %w", err)
}
if padreader.PaddedSize(uint64(payloadSize)) != pieceSize {
return nil, xerrors.Errorf("assert car(%s) file to piece fail payload size(%d) piece size (%d)", inpath, payloadSize, pieceSize)
}
if addPadding {
// make sure fd point to the end of file
// better to check within carv1.PadCar, for now is a workaround
if _, err := rdr.Seek(carSize, io.SeekStart); err != nil {
return nil, xerrors.Errorf("seek to start: %w", err)
}
if err := carv1.PadCar(rdr, carSize); err != nil {
return nil, xerrors.Errorf("failed to pad car file: %w", err)
}
}
if rename {
piecePath := path.Join(dir, commP.String())
err = os.Rename(inpath, piecePath)
if err != nil {
return nil, xerrors.Errorf("rename car(%s) file to piece %w", inpath, err)
}
}
return &CommPRet{
Root: commP,
Size: pieceSize,
PayloadSize: payloadSize,
}, nil
}