bindings_test.go 5.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package go_sectorbuilder_test

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

	sb "github.com/filecoin-project/go-sectorbuilder"
15
	"github.com/filecoin-project/go-sectorbuilder/sealed_sector_health"
16
	"github.com/filecoin-project/go-sectorbuilder/sealing_state"
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

	"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)

35
36
37
38
39
	// verify that we've not yet sealed a sector
	sealedSectors, err := sb.GetAllSealedSectorsWithHealth(ptr)
	require.NoError(t, err)
	require.Equal(t, 0, len(sealedSectors), "expected to see zero sealed sectors")

40
41
42
43
44
45
46
	// 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)
47
48
49
	read, err := io.ReadFull(rand.Reader, pieceBytes)
	require.Equal(t, uint64(read), maxPieceSize)

50
	require.NoError(t, err)
51
	pieceFile := requireTempFile(t, bytes.NewReader(pieceBytes), maxPieceSize)
52
53

	// generate piece commitment
54
55
56
57
58
	commP, err := sb.GeneratePieceCommitmentFromFile(pieceFile, maxPieceSize)
	require.NoError(t, err)

	// seek to the beginning
	_, err = pieceFile.Seek(0, 0)
59
60
61
62
	require.NoError(t, err)

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

Sidney Keese's avatar
Sidney Keese committed
66
	stagedSectors, err := sb.GetAllStagedSectors(ptr)
67
	require.NoError(t, err)
Sidney Keese's avatar
Sidney Keese committed
68
69
70
71
	require.Equal(t, 1, len(stagedSectors))
	stagedSector := stagedSectors[0]
	require.Equal(t, uint64(1), stagedSector.SectorID)

72
73
	// block until Groth parameter cache is (lazily) hydrated and sector has
	// been sealed (or timeout)
74
	status, err := pollForSectorSealingStatus(ptr, sectorID, sealing_state.Sealed, time.Minute*30)
75
76
77
78
	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
79
	isValid, err := sb.VerifySeal(1024, status.CommR, status.CommD, status.CommRStar, [31]byte{}, sectorID, status.Proof)
80
81
82
83
84
85
86
87
	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)

88
89
90
91
92
93
	// enforces sort ordering of SectorInfo tuples
	sectorInfo := sb.NewSortedSectorInfo(sb.SectorInfo{
		SectorID: status.SectorID,
		CommR:    status.CommR,
	})

94
	// generate a PoSt
95
	proofs, err := sb.GeneratePoSt(ptr, sectorInfo, [32]byte{}, []uint64{})
96
97
98
	require.NoError(t, err)

	// verify the PoSt
99
	isValid, err = sb.VerifyPoSt(1024, sectorInfo, [32]byte{}, proofs, []uint64{})
100
	require.NoError(t, err)
101
102
	require.True(t, isValid)

103
	sealedSectors, err = sb.GetAllSealedSectorsWithHealth(ptr)
104
	require.NoError(t, err)
Sidney Keese's avatar
Sidney Keese committed
105
106
107
108
	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))
109
	require.Equal(t, sealed_sector_health.Ok, sealedSector.Health)
Sidney Keese's avatar
Sidney Keese committed
110
	// the piece is the size of the sector, so its piece commitment should be the
Sidney Keese's avatar
Sidney Keese committed
111
	// data commitment
Sidney Keese's avatar
Sidney Keese committed
112
113
	require.Equal(t, commP, sealedSector.CommD)

114
115
116
	// 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")
117
	require.NoError(t, err)
118
119
120
	require.Equal(t, pieceBytes, unsealedPieceBytes)
}

121
func pollForSectorSealingStatus(ptr unsafe.Pointer, sectorID uint64, targetState sealing_state.State, timeout time.Duration) (status sb.SectorSealingStatus, retErr error) {
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
	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
			}

138
			if sealingStatus.State == targetState {
139
140
141
142
143
144
145
				status = sealingStatus
				return
			}
		}
	}
}

146
func requireTempFile(t *testing.T, fileContentsReader io.Reader, size uint64) *os.File {
147
148
149
	file, err := ioutil.TempFile("", "")
	require.NoError(t, err)

150
151
152
153
154
155
156
157
158
	written, err := io.Copy(file, fileContentsReader)
	require.NoError(t, err)
	// check that we wrote everything
	require.Equal(t, uint64(written), size)

	require.NoError(t, file.Sync())

	// seek to the beginning
	_, err = file.Seek(0, 0)
159
160
	require.NoError(t, err)

161
	return file
162
163
164
165
166
167
168
169
}

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

	return dir
}