bindings_test.go 4.69 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
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)

33
34
35
36
37
	// 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")

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
	// 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
58
	stagedSectors, err := sb.GetAllStagedSectors(ptr)
59
	require.NoError(t, err)
Sidney Keese's avatar
Sidney Keese committed
60
61
62
63
	require.Equal(t, 1, len(stagedSectors))
	stagedSector := stagedSectors[0]
	require.Equal(t, uint64(1), stagedSector.SectorID)

64
65
66
67
68
69
70
	// 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
71
	isValid, err := sb.VerifySeal(1024, status.CommR, status.CommD, status.CommRStar, [31]byte{}, sectorID, status.Proof)
72
73
74
75
76
77
78
79
	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)

80
81
82
83
84
85
	// enforces sort ordering of SectorInfo tuples
	sectorInfo := sb.NewSortedSectorInfo(sb.SectorInfo{
		SectorID: status.SectorID,
		CommR:    status.CommR,
	})

86
	// generate a PoSt
87
	proofs, err := sb.GeneratePoSt(ptr, sectorInfo, [32]byte{}, []uint64{})
88
89
90
	require.NoError(t, err)

	// verify the PoSt
91
	isValid, err = sb.VerifyPoSt(1024, sectorInfo, [32]byte{}, proofs, []uint64{})
92
	require.NoError(t, err)
93
94
	require.True(t, isValid)

95
	sealedSectors, err = sb.GetAllSealedSectorsWithHealth(ptr)
96
	require.NoError(t, err)
Sidney Keese's avatar
Sidney Keese committed
97
98
99
100
	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))
101
	require.Equal(t, sb.Ok, sealedSector.Health)
Sidney Keese's avatar
Sidney Keese committed
102
	// the piece is the size of the sector, so its piece commitment should be the
Sidney Keese's avatar
Sidney Keese committed
103
	// data commitment
Sidney Keese's avatar
Sidney Keese committed
104
105
	require.Equal(t, commP, sealedSector.CommD)

106
107
108
	// 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")
109
	require.NoError(t, err)
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
148
149
150
151
152
153
	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
}