/
address.go
113 lines (89 loc) · 2.18 KB
/
address.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
package types
import (
"bytes"
"crypto/sha512"
"fmt"
"github.com/btcsuite/btcutil/base58"
"github.com/denkhaus/bitshares/config"
"github.com/denkhaus/bitshares/util"
"github.com/juju/errors"
"github.com/pquerna/ffjson/ffjson"
)
type Address struct {
prefix string
data []byte
checksum []byte
}
func (p *Address) UnmarshalJSON(data []byte) error {
var add string
if err := ffjson.Unmarshal(data, &add); err != nil {
return errors.Annotate(err, "Unmarshal")
}
address, err := NewAddressFromString(add)
if err != nil {
return errors.Annotate(err, "NewAddressFromString")
}
p.data = address.data
p.prefix = address.prefix
p.checksum = address.checksum
return nil
}
func (p Address) MarshalJSON() ([]byte, error) {
return ffjson.Marshal(p.String())
}
func (p Address) Marshal(enc *util.TypeEncoder) error {
return enc.Encode(p.Bytes())
}
func (p Address) String() string {
b := append(p.data, p.checksum...)
return fmt.Sprintf("%s%s", p.prefix, base58.Encode(b))
}
func (p Address) Bytes() []byte {
return p.data
}
func NewAddress(pub *PublicKey) (*Address, error) {
buf512 := sha512.Sum512(pub.Bytes())
data, err := util.Ripemd160(buf512[:])
if err != nil {
return nil, errors.Annotate(err, "Ripemd160")
}
chk1, err := util.Ripemd160Checksum(data)
if err != nil {
return nil, errors.Annotate(err, "Ripemd160Checksum")
}
ad := Address{
prefix: pub.prefix,
data: data,
checksum: chk1,
}
return &ad, nil
}
//NewAddress creates a new Address from string
//e.g.("BTSFN9r6VYzBK8EKtMewfNbfiGCr56pHDBFi")
func NewAddressFromString(add string) (*Address, error) {
cnf := config.CurrentConfig()
prefixChain := cnf.Prefix()
prefix := add[:len(prefixChain)]
if prefix != prefixChain {
return nil, ErrAddressChainPrefixMismatch
}
b58 := base58.Decode(add[len(prefixChain):])
if len(b58) < 5 {
return nil, ErrInvalidAddress
}
chk1 := b58[len(b58)-4:]
data := b58[:len(b58)-4]
chk2, err := util.Ripemd160Checksum(data)
if err != nil {
return nil, errors.Annotate(err, "Ripemd160Checksum")
}
if !bytes.Equal(chk1, chk2) {
return nil, ErrInvalidAddress
}
a := Address{
data: data,
prefix: prefix,
checksum: chk1,
}
return &a, nil
}