func BatchUnmarshalPoints(curve elliptic.Curve, data [][]byte) ([]*Point, error) {
	if curve == nil {
		return nil, ErrUnspecifiedCurve
	}
	decoded := make([]*Point, len(data))
	for i := 0; i < len(data); i++ {
		p := &Point{Curve: curve, X: nil, Y: nil}
		err := p.Unmarshal(curve, data[i])
		if err != nil {
			return nil, err
		}
		decoded[i] = p
	}
	return decoded, nil
}
BatchUnmarshalPoints takes a slice of P-256 curve points in the form specified
in section 4.3.6 of ANSI X9.62 (see Go crypto/elliptic) and returns a slice
of crypto.Point instances.
package crypto
import (
	"bytes"
	"crypto"
	"crypto/elliptic"
	"crypto/rand"
	"encoding/json"
	"errors"
	"io"
	"math/big"
)
var (
	ErrInvalidPoint     = errors.New("marshaled point was invalid")
	ErrNoPointFound     = errors.New("hash_to_curve failed to find a point")
	ErrPointOffCurve    = errors.New("point is not on curve")
	ErrUnspecifiedCurve = errors.New("must specify an elliptic curve")
	ErrCommSanityCheck  = errors.New("commitment does not match key")
)
type Point struct {
	Curve elliptic.Curve
	X, Y  *big.Int
}
func (p *Point) IsOnCurve() bool {
	return p.Curve.IsOnCurve(p.X, p.Y)
}
func (p *Point) MarshalJSON() ([]byte, error) {
	byteRepr := p.Marshal()
	jsonRepr, err := json.Marshal(byteRepr)
	if err != nil {
		return nil, err
	}
	return jsonRepr, nil
}
func (p *Point) UnmarshalJSON(data []byte) error {
	var byteRepr []byte
	err := json.Unmarshal(data, byteRepr)
	if err != nil {
		return err
	}
	return p.Unmarshal(p.Curve, data)
}
func (p *Point) Marshal() []byte {
	return elliptic.Marshal(p.Curve, p.X, p.Y)
}
func (p *Point) Unmarshal(curve elliptic.Curve, data []byte) error {
	if curve == nil {
		return ErrUnspecifiedCurve
	}
	byteLen := (curve.Params().BitSize + 7) >> 3
	fieldOrder := curve.Params().P
	if len(data) == byteLen+1 {
		x := new(big.Int).SetBytes(data[1 : 1+byteLen])
		if x.Cmp(fieldOrder) != -1 {
			return ErrInvalidPoint
		}
		if data[0] == 0x02 || data[0] == 0x03 {
			sign := data[0] & 1  
			x3 := new(big.Int).Mul(x, x)           
			x3.Mul(x3, x)                          
			threeTimesX := new(big.Int).Lsh(x, 1)  
			threeTimesX.Add(threeTimesX, x)        
			x3.Sub(x3, threeTimesX)                
			x3.Add(x3, curve.Params().B)           
			y := x3.ModSqrt(x3, fieldOrder)        
			if y == nil {
				return ErrInvalidPoint
			}
			if sign != isOdd(y) {
				y.Sub(fieldOrder, y)
			}
			if !curve.IsOnCurve(x, y) {
				x = nil
				y = nil
				return ErrInvalidPoint
			}
			p.Curve = curve
			p.X, p.Y = x, y
			return nil
		}
		return ErrInvalidPoint
	}
	if len(data) == (2*byteLen)+1 && data[0] == 0x04 {
		p.Curve = curve
		p.X, p.Y = elliptic.Unmarshal(curve, data)
		if p.X == nil {
			return ErrInvalidPoint
		}
		return nil
	}
	return ErrInvalidPoint
}
func isOdd(x *big.Int) byte {
	return byte(x.Bit(0) & 1)
}