OSDN Git Service

30e8a041c78733f85683e37db514d9b58e94745c
[bytom/bytom.git] / common / types.go
1 // Copyright 2015 The go-ethereum Authors
2 // This file is part of the go-ethereum library.
3 //
4 // The go-ethereum library is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // The go-ethereum library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public License
15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16
17 package common
18
19 import (
20         _"encoding/hex"
21         "encoding/json"
22         "errors"
23         "fmt"
24         "math/big"
25         "math/rand"
26         "reflect"
27         "strings"
28 )
29
30 const (
31         HashLength    = 32
32         AddressLength = 42
33         PubkeyHashLength = 20
34 )
35
36 var hashJsonLengthErr = errors.New("common: unmarshalJSON failed: hash must be exactly 32 bytes")
37
38 type (
39         Hash    [HashLength]byte
40         Address [AddressLength]byte
41 )
42
43 func BytesToHash(b []byte) Hash {
44         var h Hash
45         h.SetBytes(b)
46         return h
47 }
48 func StringToHash(s string) Hash { return BytesToHash([]byte(s)) }
49 func BigToHash(b *big.Int) Hash  { return BytesToHash(b.Bytes()) }
50 func HexToHash(s string) Hash    { return BytesToHash(FromHex(s)) }
51
52
53 // Don't use the default 'String' method in case we want to overwrite
54
55 // Get the string representation of the underlying hash
56 func (h Hash) Str() string   { return string(h[:]) }
57 func (h Hash) Bytes() []byte { return h[:] }
58 func (h Hash) Big() *big.Int { return Bytes2Big(h[:]) }
59 func (h Hash) Hex() string   { return "0x" + Bytes2Hex(h[:]) }
60
61 // UnmarshalJSON parses a hash in its hex from to a hash.
62 func (h *Hash) UnmarshalJSON(input []byte) error {
63         length := len(input)
64         if length >= 2 && input[0] == '"' && input[length-1] == '"' {
65                 input = input[1 : length-1]
66         }
67         // strip "0x" for length check
68         if len(input) > 1 && strings.ToLower(string(input[:2])) == "0x" {
69                 input = input[2:]
70         }
71
72         // validate the length of the input hash
73         if len(input) != HashLength*2 {
74                 return hashJsonLengthErr
75         }
76         h.SetBytes(FromHex(string(input)))
77         return nil
78 }
79
80 // Serialize given hash to JSON
81 func (h Hash) MarshalJSON() ([]byte, error) {
82         return json.Marshal(h.Hex())
83 }
84
85 // Sets the hash to the value of b. If b is larger than len(h) it will panic
86 func (h *Hash) SetBytes(b []byte) {
87         if len(b) > len(h) {
88                 b = b[len(b)-HashLength:]
89         }
90
91         copy(h[HashLength-len(b):], b)
92 }
93
94 // Set string `s` to h. If s is larger than len(h) it will panic
95 func (h *Hash) SetString(s string) { h.SetBytes([]byte(s)) }
96
97 // Sets h to other
98 func (h *Hash) Set(other Hash) {
99         for i, v := range other {
100                 h[i] = v
101         }
102 }
103
104 // Generate implements testing/quick.Generator.
105 func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
106         m := rand.Intn(len(h))
107         for i := len(h) - 1; i > m; i-- {
108                 h[i] = byte(rand.Uint32())
109         }
110         return reflect.ValueOf(h)
111 }
112
113 func EmptyHash(h Hash) bool {
114         return h == Hash{}
115 }
116
117 /////////// Address
118 func BytesToAddress(b []byte) Address {
119         var a Address
120         a.SetBytes(b)
121         return a
122 }
123 func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) }
124 func BigToAddress(b *big.Int) Address  { return BytesToAddress(b.Bytes()) }
125 func HexToAddress(s string) Address    { return BytesToAddress(FromHex(s)) }
126
127 // IsHexAddress verifies whether a string can represent a valid hex-encoded
128 // Ethereum address or not.
129 func IsHexAddress(s string) bool {
130         if len(s) == 2+2*AddressLength && IsHex(s) {
131                 return true
132         }
133         if len(s) == 2*AddressLength && IsHex("0x"+s) {
134                 return true
135         }
136         return false
137 }
138
139 // Get the string representation of the underlying address
140 func (a Address) Str() string   { return string(a[:]) }
141 func (a Address) Bytes() []byte { return a[:] }
142 func (a Address) Big() *big.Int { return Bytes2Big(a[:]) }
143 func (a Address) Hash() Hash    { return BytesToHash(a[:]) }
144 func (a Address) Hex() string   { return "0x" + Bytes2Hex(a[:]) }
145
146 // Sets the address to the value of b. If b is larger than len(a) it will panic
147 func (a *Address) SetBytes(b []byte) {
148         if len(b) > len(a) {
149                 b = b[len(b)-AddressLength:]
150         }
151         copy(a[AddressLength-len(b):], b)
152 }
153
154 // Set string `s` to a. If s is larger than len(a) it will panic
155 func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) }
156
157 // Sets a to other
158 func (a *Address) Set(other Address) {
159         for i, v := range other {
160                 a[i] = v
161         }
162 }
163
164 // Serialize given address to JSON
165 func (a Address) MarshalJSON() ([]byte, error) {
166         return json.Marshal(a.Str())
167 }
168
169 // Parse address from raw json data
170 func (a *Address) UnmarshalJSON(data []byte) error {
171         if len(data) > 2 && data[0] == '"' && data[len(data)-1] == '"' {
172                 data = data[1 : len(data)-1]
173         }
174
175         if len(data) != AddressLength {
176                 return fmt.Errorf("Invalid address length, expected %d got %d bytes", AddressLength, len(data))
177         }
178
179         _, res, err := AddressDecode("bm", string(data))
180         if err != nil {
181                 return err
182         }
183
184         if len(res) != PubkeyHashLength {
185                 return fmt.Errorf("Invalid address")
186         }
187         a.Set(BytesToAddress(data))
188         return nil
189 }
190
191 // PP Pretty Prints a byte slice in the following format:
192 //      hex(value[:4])...(hex[len(value)-4:])
193 func PP(value []byte) string {
194         if len(value) <= 8 {
195                 return Bytes2Hex(value)
196         }
197
198         return fmt.Sprintf("%x...%x", value[:4], value[len(value)-4])
199 }