-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathproviderutils.go
119 lines (101 loc) · 4.5 KB
/
providerutils.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Package providerutils provides utility functions for the storage provider & provider FSM
package providerutils
import (
"context"
"github.com/ipfs/go-cid"
"github.com/ipld/go-car"
"github.com/ipld/go-ipld-prime"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/go-fil-markets/filestore"
"github.com/filecoin-project/go-fil-markets/piecestore"
"github.com/filecoin-project/go-fil-markets/shared"
"github.com/filecoin-project/go-fil-markets/storagemarket/impl/blockrecorder"
)
// VerifyFunc is a function that can validate a signature for a given address and bytes
type VerifyFunc func(context.Context, crypto.Signature, address.Address, []byte, shared.TipSetToken) (bool, error)
// VerifyProposal verifies the signature on the given signed proposal matches
// the client addres for the proposal, using the given signature verification function
func VerifyProposal(ctx context.Context, sdp market.ClientDealProposal, tok shared.TipSetToken, verifier VerifyFunc) error {
b, err := cborutil.Dump(&sdp.Proposal)
if err != nil {
return err
}
return VerifySignature(ctx, sdp.ClientSignature, sdp.Proposal.Client, b, tok, verifier)
}
// VerifySignature verifies the signature over the given bytes
func VerifySignature(ctx context.Context, signature crypto.Signature, signer address.Address, buf []byte, tok shared.TipSetToken, verifier VerifyFunc) error {
verified, err := verifier(ctx, signature, signer, buf, tok)
if err != nil {
return xerrors.Errorf("verifying: %w", err)
}
if !verified {
return xerrors.New("could not verify signature")
}
return nil
}
// WorkerLookupFunc is a function that can lookup a miner worker address from a storage miner actor
type WorkerLookupFunc func(context.Context, address.Address, shared.TipSetToken) (address.Address, error)
// SignFunc is a function that can sign a set of bytes with a given address
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
// SignMinerData signs the given data structure with a signature for the given address
func SignMinerData(ctx context.Context, data interface{}, address address.Address, tok shared.TipSetToken, workerLookup WorkerLookupFunc, sign SignFunc) (*crypto.Signature, error) {
msg, err := cborutil.Dump(data)
if err != nil {
return nil, xerrors.Errorf("serializing: %w", err)
}
worker, err := workerLookup(ctx, address, tok)
if err != nil {
return nil, err
}
sig, err := sign(ctx, worker, msg)
if err != nil {
return nil, xerrors.Errorf("failed to sign: %w", err)
}
return sig, nil
}
// CommPGenerator is a commP generating function that writes to a file
type CommPGenerator func(abi.RegisteredSealProof, cid.Cid, ipld.Node, *multistore.StoreID, ...car.OnNewCarBlockFunc) (cid.Cid, abi.UnpaddedPieceSize, error)
// GeneratePieceCommitmentWithMetadata generates a piece commitment along with block metadata
func GeneratePieceCommitmentWithMetadata(
fileStore filestore.FileStore,
commPGenerator CommPGenerator,
proofType abi.RegisteredSealProof,
payloadCid cid.Cid,
selector ipld.Node,
storeID *multistore.StoreID) (cid.Cid, abi.UnpaddedPieceSize, filestore.Path, error) {
metadataFile, err := fileStore.CreateTemp(payloadCid.String())
if err != nil {
return cid.Cid{}, 0, "", err
}
blockRecorder := blockrecorder.RecordEachBlockTo(metadataFile)
pieceCid, psize, err := commPGenerator(proofType, payloadCid, selector, storeID, blockRecorder)
_ = metadataFile.Close()
if err != nil {
_ = fileStore.Delete(metadataFile.Path())
return cid.Cid{}, 0, "", err
}
return pieceCid, psize, metadataFile.Path(), err
}
// LoadBlockLocations loads a metadata file then converts it to a map of cid -> blockLocation
func LoadBlockLocations(fs filestore.FileStore, metadataPath filestore.Path) (map[cid.Cid]piecestore.BlockLocation, error) {
metadataFile, err := fs.Open(metadataPath)
if err != nil {
return nil, err
}
metadata, err := blockrecorder.ReadBlockMetadata(metadataFile)
_ = metadataFile.Close()
if err != nil {
return nil, err
}
blockLocations := make(map[cid.Cid]piecestore.BlockLocation, len(metadata))
for _, metadatum := range metadata {
blockLocations[metadatum.CID] = piecestore.BlockLocation{RelOffset: metadatum.Offset, BlockSize: metadatum.Size}
}
return blockLocations, nil
}