OSDN Git Service

fix bug action & remove ctx
[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
145 // Sets the address to the value of b. If b is larger than len(a) it will panic
146 func (a *Address) SetBytes(b []byte) {
147         if len(b) > len(a) {
148                 b = b[len(b)-AddressLength:]
149         }
150         copy(a[AddressLength-len(b):], b)
151 }
152
153 // Set string `s` to a. If s is larger than len(a) it will panic
154 func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) }
155
156 // Sets a to other
157 func (a *Address) Set(other Address) {
158         for i, v := range other {
159                 a[i] = v
160         }
161 }
162
163 // Serialize given address to JSON
164 func (a Address) MarshalJSON() ([]byte, error) {
165         return json.Marshal(a.Str())
166 }
167
168 // Parse address from raw json data
169 func (a *Address) UnmarshalJSON(data []byte) error {
170         if len(data) > 2 && data[0] == '"' && data[len(data)-1] == '"' {
171                 data = data[1 : len(data)-1]
172         }
173
174         if len(data) != AddressLength {
175                 return fmt.Errorf("Invalid address length, expected %d got %d bytes", AddressLength, len(data))
176         }
177
178         _, res, err := AddressDecode("bm", string(data))
179         if err != nil {
180                 return err
181         }
182
183         if len(res) != PubkeyHashLength {
184                 return fmt.Errorf("Invalid address")
185         }
186         a.Set(BytesToAddress(data))
187         return nil
188 }
189
190 // PP Pretty Prints a byte slice in the following format:
191 //      hex(value[:4])...(hex[len(value)-4:])
192 func PP(value []byte) string {
193         if len(value) <= 8 {
194                 return Bytes2Hex(value)
195         }
196
197         return fmt.Sprintf("%x...%x", value[:4], value[len(value)-4])
198 }