transforms.go 4.6 KB
Newer Older
1
package go_sectorbuilder
2
3
4

import (
	"unsafe"
Sidney Keese's avatar
Sidney Keese committed
5

6
7
	"github.com/filecoin-project/go-sectorbuilder/sealed_sector_health"

Sidney Keese's avatar
Sidney Keese committed
8
	"github.com/pkg/errors"
9
10
)

11
12
13
// #cgo LDFLAGS: ${SRCDIR}/libsector_builder_ffi.a
// #cgo pkg-config: ${SRCDIR}/sector_builder_ffi.pc
// #include "./sector_builder_ffi.h"
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import "C"

// SingleProofPartitionProofLen denotes the number of bytes in a proof generated
// with a single partition. The number of bytes in a proof increases linearly
// with the number of partitions used when creating that proof.
const SingleProofPartitionProofLen = 192

func cUint64s(src []uint64) (*C.uint64_t, C.size_t) {
	srcCSizeT := C.size_t(len(src))

	// allocate array in C heap
	cUint64s := C.malloc(srcCSizeT * C.sizeof_uint64_t)

	// create a Go slice backed by the C-array
	pp := (*[1 << 30]C.uint64_t)(cUint64s)
	for i, v := range src {
		pp[i] = C.uint64_t(v)
	}

	return (*C.uint64_t)(cUint64s), srcCSizeT
}

laser's avatar
laser committed
36
func cSectorClass(sectorSize uint64, poRepProofPartitions uint8) (C.sector_builder_ffi_FFISectorClass, error) {
37
38
39
40
41
42
43
44
45
46
	return C.sector_builder_ffi_FFISectorClass{
		sector_size:            C.uint64_t(sectorSize),
		porep_proof_partitions: C.uint8_t(poRepProofPartitions),
	}, nil
}

func goBytes(src *C.uint8_t, size C.size_t) []byte {
	return C.GoBytes(unsafe.Pointer(src), C.int(size))
}

47
48
49
50
51
52
53
54
55
56
57
func goSealTicket(src C.sector_builder_ffi_FFISealTicket) SealTicket {
	ticketBytesSlice := C.GoBytes(unsafe.Pointer(&src.ticket_bytes[0]), 32)
	var ticketBytes [CommitmentBytesLen]byte
	copy(ticketBytes[:], ticketBytesSlice)

	return SealTicket{
		TicketBytes: ticketBytes,
		BlockHeight: uint64(src.block_height),
	}
}

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
func goStagedSectorMetadata(src *C.sector_builder_ffi_FFIStagedSectorMetadata, size C.size_t) ([]StagedSectorMetadata, error) {
	sectors := make([]StagedSectorMetadata, size)
	if src == nil || size == 0 {
		return sectors, nil
	}

	sectorPtrs := (*[1 << 30]C.sector_builder_ffi_FFIStagedSectorMetadata)(unsafe.Pointer(src))[:size:size]
	for i := 0; i < int(size); i++ {
		sectors[i] = StagedSectorMetadata{
			SectorID: uint64(sectorPtrs[i].sector_id),
		}
	}

	return sectors, nil
}

Sidney Keese's avatar
Sidney Keese committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
func goSealedSectorMetadata(src *C.sector_builder_ffi_FFISealedSectorMetadata, size C.size_t) ([]SealedSectorMetadata, error) {
	sectors := make([]SealedSectorMetadata, size)
	if src == nil || size == 0 {
		return sectors, nil
	}

	ptrs := (*[1 << 30]C.sector_builder_ffi_FFISealedSectorMetadata)(unsafe.Pointer(src))[:size:size]
	for i := 0; i < int(size); i++ {
		commDSlice := goBytes(&ptrs[i].comm_d[0], CommitmentBytesLen)
		var commD [CommitmentBytesLen]byte
		copy(commD[:], commDSlice)

		commRSlice := goBytes(&ptrs[i].comm_r[0], CommitmentBytesLen)
		var commR [CommitmentBytesLen]byte
		copy(commR[:], commRSlice)

		proof := goBytes(ptrs[i].proofs_ptr, ptrs[i].proofs_len)

		pieces, err := goPieceMetadata(ptrs[i].pieces_ptr, ptrs[i].pieces_len)
		if err != nil {
			return []SealedSectorMetadata{}, errors.Wrap(err, "failed to marshal piece metadata")
		}

97
98
99
100
101
		health, err := goSealedSectorHealth(ptrs[i].health)
		if err != nil {
			return []SealedSectorMetadata{}, errors.Wrap(err, "failed to marshal sealed sector health")
		}

Sidney Keese's avatar
Sidney Keese committed
102
		sectors[i] = SealedSectorMetadata{
103
104
105
106
107
108
109
			SectorID: uint64(ptrs[i].sector_id),
			CommD:    commD,
			CommR:    commR,
			Proof:    proof,
			Pieces:   pieces,
			Health:   health,
			Ticket:   goSealTicket(ptrs[i].seal_ticket),
Sidney Keese's avatar
Sidney Keese committed
110
111
112
113
114
115
		}
	}

	return sectors, nil
}

116
117
118
119
120
121
122
123
func goPieceMetadata(src *C.sector_builder_ffi_FFIPieceMetadata, size C.size_t) ([]PieceMetadata, error) {
	ps := make([]PieceMetadata, size)
	if src == nil || size == 0 {
		return ps, nil
	}

	ptrs := (*[1 << 30]C.sector_builder_ffi_FFIPieceMetadata)(unsafe.Pointer(src))[:size:size]
	for i := 0; i < int(size); i++ {
124
125
126
127
		commPSlice := goBytes(&ptrs[i].comm_p[0], CommitmentBytesLen)
		var commP [CommitmentBytesLen]byte
		copy(commP[:], commPSlice)

128
		ps[i] = PieceMetadata{
129
130
131
132
			Key:            C.GoString(ptrs[i].piece_key),
			Size:           uint64(ptrs[i].num_bytes),
			CommP:          commP,
			InclusionProof: goBytes(ptrs[i].piece_inclusion_proof_ptr, ptrs[i].piece_inclusion_proof_len),
133
134
135
136
137
		}
	}

	return ps, nil
}
138

139
func goSealedSectorHealth(health C.sector_builder_ffi_FFISealedSectorHealth) (sealed_sector_health.Health, error) {
140
	switch health {
141
	case C.Unknown:
142
		return sealed_sector_health.Unknown, nil
143
	case C.Ok:
144
		return sealed_sector_health.Ok, nil
145
	case C.ErrorInvalidChecksum:
146
		return sealed_sector_health.InvalidChecksum, nil
147
	case C.ErrorInvalidLength:
148
		return sealed_sector_health.InvalidLength, nil
149
	case C.ErrorMissing:
150
		return sealed_sector_health.Missing, nil
151
	default:
152
		return sealed_sector_health.Unknown, errors.Errorf("unhandled sealed sector health: %v", health)
153
154
	}
}