bindings_test.go 4.43 KB
Newer Older
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
package go_sectorbuilder_test

import (
	"bytes"
	"crypto/rand"
	"errors"
	"io"
	"io/ioutil"
	"os"
	"testing"
	"time"
	"unsafe"

	sb "github.com/filecoin-project/go-sectorbuilder"

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

func TestSectorBuilderLifecycle(t *testing.T) {
	metadataDir := requireTempDirPath(t)
	defer require.NoError(t, os.Remove(metadataDir))

	sealedSectorDir := requireTempDirPath(t)
	defer require.NoError(t, os.Remove(sealedSectorDir))

	stagedSectorDir := requireTempDirPath(t)
	defer require.NoError(t, os.Remove(stagedSectorDir))

	ptr, err := sb.InitSectorBuilder(1024, 2, 1, 0, metadataDir, [31]byte{}, sealedSectorDir, stagedSectorDir, 1)
	require.NoError(t, err)
	defer sb.DestroySectorBuilder(ptr)

	// compute the max user-bytes that can fit into a staged sector such that
	// bit-padding ("preprocessing") expands the file to $SECTOR_SIZE
	maxPieceSize := sb.GetMaxUserBytesPerStagedSector(1024)

	// create a piece which consumes all available space in a new, staged
	// sector
	pieceBytes := make([]byte, maxPieceSize)
	_, err = io.ReadFull(rand.Reader, pieceBytes)
	require.NoError(t, err)
	piecePath := requireTempFilePath(t, bytes.NewReader(pieceBytes))

	// generate piece commitment
	commP, err := sb.GeneratePieceCommitment(piecePath, maxPieceSize)
	require.NoError(t, err)

	// write a piece to a staged sector, reducing remaining space to 0 and
	// triggering the seal job
	sectorID, err := sb.AddPiece(ptr, "snoqualmie", maxPieceSize, piecePath)
	require.NoError(t, err)

Sidney Keese's avatar
Sidney Keese committed
53
	stagedSectors, err := sb.GetAllStagedSectors(ptr)
54
	require.NoError(t, err)
Sidney Keese's avatar
Sidney Keese committed
55
56
57
58
	require.Equal(t, 1, len(stagedSectors))
	stagedSector := stagedSectors[0]
	require.Equal(t, uint64(1), stagedSector.SectorID)

59
60
61
62
63
64
65
	// block until Groth parameter cache is (lazily) hydrated and sector has
	// been sealed (or timeout)
	status, err := pollForSectorSealingStatus(ptr, sectorID, 0, time.Minute*30)
	require.NoError(t, err)
	require.Equal(t, 1, len(status.Pieces), "expected to see the one piece we added")

	// verify the seal proof
laser's avatar
laser committed
66
	isValid, err := sb.VerifySeal(1024, status.CommR, status.CommD, status.CommRStar, [31]byte{}, sectorID, status.Proof)
67
68
69
70
71
72
73
74
	require.NoError(t, err)
	require.True(t, isValid)

	// verify the piece inclusion proof
	isValid, err = sb.VerifyPieceInclusionProof(1024, maxPieceSize, commP, status.CommD, status.Pieces[0].InclusionProof)
	require.NoError(t, err)
	require.True(t, isValid)

75
76
77
78
79
80
	// enforces sort ordering of SectorInfo tuples
	sectorInfo := sb.NewSortedSectorInfo(sb.SectorInfo{
		SectorID: status.SectorID,
		CommR:    status.CommR,
	})

81
	// generate a PoSt
82
	proofs, err := sb.GeneratePoSt(ptr, sectorInfo, [32]byte{}, []uint64{})
83
84
85
	require.NoError(t, err)

	// verify the PoSt
86
	isValid, err = sb.VerifyPoSt(1024, sectorInfo, [32]byte{}, proofs, []uint64{})
87
	require.NoError(t, err)
88
89
	require.True(t, isValid)

Sidney Keese's avatar
Sidney Keese committed
90
	sealedSectors, err := sb.GetAllSealedSectors(ptr)
91
	require.NoError(t, err)
Sidney Keese's avatar
Sidney Keese committed
92
93
94
95
96
	require.Equal(t, 1, len(sealedSectors), "expected to see one sealed sector")
	sealedSector := sealedSectors[0]
	require.Equal(t, uint64(1), sealedSector.SectorID)
	require.Equal(t, 1, len(sealedSector.Pieces))
	// the piece is the size of the sector, so its piece commitment should be the
Sidney Keese's avatar
Sidney Keese committed
97
	// data commitment
Sidney Keese's avatar
Sidney Keese committed
98
99
	require.Equal(t, commP, sealedSector.CommD)

100
101
102
	// unseal the sector and retrieve the client's piece, verifying that the
	// retrieved bytes match what we originally wrote to the staged sector
	unsealedPieceBytes, err := sb.ReadPieceFromSealedSector(ptr, "snoqualmie")
103
	require.NoError(t, err)
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
	require.Equal(t, pieceBytes, unsealedPieceBytes)
}

func pollForSectorSealingStatus(ptr unsafe.Pointer, sectorID uint64, sealStatusCode uint8, timeout time.Duration) (status sb.SectorSealingStatus, retErr error) {
	timeoutCh := time.After(timeout)

	tick := time.Tick(5 * time.Second)

	for {
		select {
		case <-timeoutCh:
			retErr = errors.New("timed out waiting for sector to finish sealing")
			return
		case <-tick:
			sealingStatus, err := sb.GetSectorSealingStatusByID(ptr, sectorID)
			if err != nil {
				retErr = err
				return
			}

			if sealingStatus.SealStatusCode == sealStatusCode {
				status = sealingStatus
				return
			}
		}
	}
}

func requireTempFilePath(t *testing.T, fileContentsReader io.Reader) string {
	file, err := ioutil.TempFile("", "")
	require.NoError(t, err)

	_, err = io.Copy(file, fileContentsReader)
	require.NoError(t, err)

	return file.Name()
}

func requireTempDirPath(t *testing.T) string {
	dir, err := ioutil.TempDir("", "")
	require.NoError(t, err)

	return dir
}