You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
3.4 KiB

package merkletree
import (
"bytes"
"encoding/hex"
"fmt"
cryptoUtils "github.com/iden3/go-iden3-crypto/utils"
"math/big"
"strings"
)
var (
// HashZero is used at Empty nodes
HashZero = Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
)
// Hash is the generic type stored in the MerkleTree
type Hash [32]byte
// MarshalText implements the marshaler for the Hash type
func (h Hash) MarshalText() ([]byte, error) {
return []byte(h.BigInt().String()), nil
}
// UnmarshalText implements the unmarshaler for the Hash type
func (h *Hash) UnmarshalText(b []byte) error {
ha, err := NewHashFromString(string(b))
copy(h[:], ha[:])
return err
}
// String returns decimal representation in string format of the Hash
func (h Hash) String() string {
s := h.BigInt().String()
if len(s) < numCharPrint {
return s
}
return s[0:numCharPrint] + "..."
}
// Hex returns the hexadecimal representation of the Hash
func (h Hash) Hex() string {
return hex.EncodeToString(h[:])
// alternatively equivalent, but with too extra steps:
// bRaw := h.BigInt().Bytes()
// b := [32]byte{}
// copy(b[:], SwapEndianness(bRaw[:]))
// return hex.EncodeToString(b[:])
}
// BigInt returns the *big.Int representation of the *Hash
func (h *Hash) BigInt() *big.Int {
if new(big.Int).SetBytes(SwapEndianness(h[:])) == nil {
return big.NewInt(0)
}
return new(big.Int).SetBytes(SwapEndianness(h[:]))
}
// Bytes returns the []byte representation of the *Hash, which always is 32
// bytes length.
func (h *Hash) Bytes() []byte {
bi := new(big.Int).SetBytes(h[:]).Bytes()
b := [32]byte{}
copy(b[:], SwapEndianness(bi[:]))
return b[:]
}
func (h *Hash) Equals(h2 *Hash) bool {
return bytes.Equal(h[:], h2[:])
}
// NewBigIntFromHashBytes returns a *big.Int from a byte array, swapping the
// endianness in the process. This is the intended method to get a *big.Int
// from a byte array that previously has ben generated by the Hash.Bytes()
// method.
func NewBigIntFromHashBytes(b []byte) (*big.Int, error) {
if len(b) != ElemBytesLen {
return nil, fmt.Errorf("Expected 32 bytes, found %d bytes", len(b))
}
bi := new(big.Int).SetBytes(b[:ElemBytesLen])
if !cryptoUtils.CheckBigIntInField(bi) {
return nil, fmt.Errorf("NewBigIntFromHashBytes: Value not inside the Finite Field")
}
return bi, nil
}
// NewHashFromBigInt returns a *Hash representation of the given *big.Int
func NewHashFromBigInt(b *big.Int) *Hash {
r := &Hash{}
copy(r[:], SwapEndianness(b.Bytes()))
return r
}
// NewHashFromBytes returns a *Hash from a byte array, swapping the endianness
// in the process. This is the intended method to get a *Hash from a byte array
// that previously has ben generated by the Hash.Bytes() method.
func NewHashFromBytes(b []byte) (*Hash, error) {
if len(b) != ElemBytesLen {
return nil, fmt.Errorf("Expected 32 bytes, found %d bytes", len(b))
}
var h Hash
copy(h[:], SwapEndianness(b))
return &h, nil
}
// NewHashFromHex returns a *Hash representation of the given hex string
func NewHashFromHex(h string) (*Hash, error) {
h = strings.TrimPrefix(h, "0x")
b, err := hex.DecodeString(h)
if err != nil {
return nil, err
}
return NewHashFromBytes(SwapEndianness(b[:]))
}
// NewHashFromString returns a *Hash representation of the given decimal string
func NewHashFromString(s string) (*Hash, error) {
bi, ok := new(big.Int).SetString(s, 10)
if !ok {
return nil, fmt.Errorf("Can not parse string to Hash")
}
return NewHashFromBigInt(bi), nil
}