-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathhash.go
117 lines (103 loc) · 3.05 KB
/
hash.go
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package merkletree
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"math/big"
"strings"
cryptoUtils "github.com/iden3/go-iden3-crypto/utils"
)
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))
if err != nil {
return err
}
copy(h[:], ha[:])
return nil
}
// 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[:]))
}
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, error) {
if !cryptoUtils.CheckBigIntInField(b) {
return nil, errors.New(
"NewHashFromBigInt: Value not inside the Finite Field")
}
r := &Hash{}
copy(r[:], SwapEndianness(b.Bytes()))
return r, 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
}
var hash Hash
if len(b) != len(hash) {
return nil, errors.New("invalid hash length")
}
copy(hash[:], b)
return &hash, nil
}
// 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)
}