func Reconstruct()

in client/internal/secret_sharing/internal/shamirgeneric/shamir_generic.go [94:136]


func Reconstruct(splitSecret secrets.Split, gf field.GaloisField) ([]byte, error) {
	if err := validateReconstructInput(splitSecret); err != nil {
		return nil, err
	}
	// We only need `threshold` shares to reconstruct the secrets.
	shares := splitSecret.Shares[:splitSecret.Metadata.Threshold]
	xVals := []field.Element{}
	for _, s := range shares {
		xi, err := gf.CreateElement(s.X)
		if err != nil {
			return nil, err
		}
		xVals = append(xVals, xi)
	}
	// Precompute the Lagrange coefficients before performing polynomial interpolation.
	// The output to this step could be kept in memory, but it would require making
	// this implementation thread safe.
	coefficients, err := lagrangeCoefficients(xVals, gf)
	if err != nil {
		return nil, err
	}
	// Calculate the number of field elements per secret share based on the share size.
	var numSubSecrets = len(shares[0].Value) / gf.ElementSize()
	subsecrets := make([]field.Element, numSubSecrets, numSubSecrets)
	for i := 0; i < numSubSecrets; i++ {
		yVals := make([]field.Element, len(xVals))

		for j, s := range shares {
			yVals[j], err = gf.ReadElement(s.Value, i)
			if err != nil {
				return nil, err
			}
		}
		// interpolatePolynomial recovers the C[0] coefficient, the geometric interpretation
		// of the intersection with the Y axis.
		subsecrets[i], err = interpolatePolynomial(coefficients, yVals, gf)
		if err != nil {
			return nil, err
		}
	}
	// combine the subsecret field elements into the original secrets.
	return gf.EncodeElements(subsecrets, splitSecret.SecretLen)
}