Skip to content

Commit 5f31a32

Browse files
Merge pull request #9 from tokenized/develop
Release
2 parents 62788f6 + 77e4f01 commit 5f31a32

36 files changed

+795
-270
lines changed

bitcoin/encode.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/base64"
55
"encoding/hex"
66
"fmt"
7+
"io"
78
"strings"
89

910
"github.com/btcsuite/btcutil/base58"
@@ -195,3 +196,42 @@ func BIP0276Decode58(url string) (Network, string, []byte, error) {
195196

196197
return net, parts[0], b, nil
197198
}
199+
200+
func ReadBase128VarInt(r io.Reader) (uint64, error) {
201+
value := uint64(0)
202+
done := false
203+
bitOffset := uint64(0)
204+
for !done {
205+
var subValue [1]byte
206+
if _, err := io.ReadFull(r, subValue[:]); err != nil {
207+
return value, err
208+
}
209+
210+
done = (subValue[0] & 0x80) == 0 // High bit not set
211+
subValue[0] = subValue[0] & 0x7f // Remove high bit
212+
213+
value += uint64(subValue[0]) << bitOffset
214+
bitOffset += 7
215+
}
216+
217+
return value, nil
218+
}
219+
220+
func WriteBase128VarInt(w io.Writer, value uint64) error {
221+
v := value
222+
for {
223+
if v < 128 {
224+
var b [1]byte
225+
b[0] = byte(v)
226+
_, err := w.Write(b[:])
227+
return err
228+
}
229+
230+
var subValue [1]byte
231+
subValue[0] = (byte(v&0x7f) | 0x80) // Get last 7 bits and set high bit
232+
if _, err := w.Write(subValue[:]); err != nil {
233+
return err
234+
}
235+
v = v >> 7
236+
}
237+
}

bitcoin/encode_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package bitcoin
2+
3+
import (
4+
"bytes"
5+
"encoding/hex"
6+
"testing"
7+
)
8+
9+
func TestBase128(t *testing.T) {
10+
tests := []struct {
11+
hex string
12+
value uint64
13+
}{
14+
{
15+
hex: "b0b8d0a2a4b081a316",
16+
value: 1604976374254410800,
17+
},
18+
{
19+
hex: "00",
20+
value: 0,
21+
},
22+
{
23+
hex: "01",
24+
value: 1,
25+
},
26+
{
27+
hex: "0f",
28+
value: 15,
29+
},
30+
{
31+
hex: "ff01",
32+
value: 255,
33+
},
34+
}
35+
36+
for _, tt := range tests {
37+
t.Run(tt.hex, func(t *testing.T) {
38+
b, err := hex.DecodeString(tt.hex)
39+
if err != nil {
40+
t.Fatal(err)
41+
}
42+
43+
value, err := ReadBase128VarInt(bytes.NewReader(b))
44+
if err != nil {
45+
t.Fatalf("Failed to read : %s", err)
46+
}
47+
48+
if value != tt.value {
49+
t.Errorf("Wrong value : got %d, want %d", value, tt.value)
50+
}
51+
52+
var w bytes.Buffer
53+
if err := WriteBase128VarInt(&w, value); err != nil {
54+
t.Fatalf("Failed to write : %s", err)
55+
}
56+
57+
if !bytes.Equal(w.Bytes(), b) {
58+
t.Errorf("Wrong hex : got %x, want %x", w.Bytes(), b)
59+
}
60+
})
61+
}
62+
}

bitcoin/encryptor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func NewDecryptor(key []byte, r io.Reader) (*Decryptor, error) {
149149

150150
// Read initialization vector (IV)
151151
iv := make([]byte, aes.BlockSize)
152-
if _, err = r.Read(iv); err != nil {
152+
if _, err = io.ReadFull(r, iv); err != nil {
153153
return nil, errors.Wrap(err, "read iv")
154154
}
155155

bitcoin/extended_key.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,13 @@ func ExtendedKeyFromBytes(b []byte) (ExtendedKey, error) {
106106
// ExtendedKeyFromBytes creates a key from bytes.
107107
func (k *ExtendedKey) Deserialize(r io.Reader) error {
108108
var header [1]byte
109-
if _, err := r.Read(header[:]); err != nil {
109+
if _, err := io.ReadFull(r, header[:]); err != nil {
110110
return errors.Wrap(err, "read header")
111111
}
112112
if header[0] != ExtendedKeyHeader {
113113
// Fall back to BIP-0032 format
114114
b := make([]byte, 82)
115-
if _, err := r.Read(b); err != nil {
115+
if _, err := io.ReadFull(r, b); err != nil {
116116
return err
117117
}
118118
bip32Key, err := bip32.Deserialize(b)
@@ -529,24 +529,24 @@ func (k *ExtendedKey) setFromBIP32(old *bip32.Key) error {
529529
// read reads just the basic data of the extended key.
530530
func (k *ExtendedKey) read(r io.Reader) error {
531531
var b [1]byte
532-
if _, err := r.Read(b[:]); err != nil {
532+
if _, err := io.ReadFull(r, b[:]); err != nil {
533533
return errors.Wrap(err, "reading xkey depth")
534534
}
535535
k.Depth = b[0]
536536

537-
if _, err := r.Read(k.FingerPrint[:]); err != nil {
537+
if _, err := io.ReadFull(r, k.FingerPrint[:]); err != nil {
538538
return errors.Wrap(err, "reading xkey fingerprint")
539539
}
540540

541541
if err := binary.Read(r, binary.BigEndian, &k.Index); err != nil {
542542
return errors.Wrap(err, "reading xkey index")
543543
}
544544

545-
if _, err := r.Read(k.ChainCode[:]); err != nil {
545+
if _, err := io.ReadFull(r, k.ChainCode[:]); err != nil {
546546
return errors.Wrap(err, "reading xkey chaincode")
547547
}
548548

549-
if _, err := r.Read(k.KeyValue[:]); err != nil {
549+
if _, err := io.ReadFull(r, k.KeyValue[:]); err != nil {
550550
return errors.Wrap(err, "reading xkey key")
551551
}
552552

bitcoin/extended_keys.go

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"encoding/hex"
66
"fmt"
7-
"io"
87

98
"github.com/pkg/errors"
109
bip32 "github.com/tyler-smith/go-bip32"
@@ -49,7 +48,7 @@ func ExtendedKeysFromBytes(b []byte) (ExtendedKeys, error) {
4948
}
5049

5150
result := make(ExtendedKeys, 0, count)
52-
for i := 0; i < count; i++ {
51+
for i := uint64(0); i < count; i++ {
5352
var ek ExtendedKey
5453
if err := ek.read(buf); err != nil {
5554
return nil, errors.Wrap(err, "read xkey base")
@@ -145,7 +144,7 @@ func (k ExtendedKeys) Bytes() []byte {
145144
return nil
146145
}
147146

148-
if err := WriteBase128VarInt(&buf, len(k)); err != nil {
147+
if err := WriteBase128VarInt(&buf, uint64(len(k))); err != nil {
149148
return nil
150149
}
151150

@@ -314,42 +313,3 @@ func (k *ExtendedKeys) Scan(data interface{}) error {
314313
copy(c, b)
315314
return k.SetBytes(c)
316315
}
317-
318-
func ReadBase128VarInt(r io.Reader) (int, error) {
319-
value := uint32(0)
320-
done := false
321-
bitOffset := uint32(0)
322-
for !done {
323-
var subValue [1]byte
324-
if _, err := r.Read(subValue[:]); err != nil {
325-
return int(value), err
326-
}
327-
328-
done = (subValue[0] & 0x80) == 0 // High bit not set
329-
subValue[0] = subValue[0] & 0x7f // Remove high bit
330-
331-
value += uint32(subValue[0]) << bitOffset
332-
bitOffset += 7
333-
}
334-
335-
return int(value), nil
336-
}
337-
338-
func WriteBase128VarInt(w io.Writer, value int) error {
339-
v := uint32(value)
340-
for {
341-
if v < 128 {
342-
var b [1]byte
343-
b[0] = byte(v)
344-
_, err := w.Write(b[:])
345-
return err
346-
}
347-
348-
var subValue [1]byte
349-
subValue[0] = (byte(v&0x7f) | 0x80) // Get last 7 bits and set high bit
350-
if _, err := w.Write(subValue[:]); err != nil {
351-
return err
352-
}
353-
v = v >> 7
354-
}
355-
}

bitcoin/hash20.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func (h Hash20) Serialize(w io.Writer) error {
8383
}
8484

8585
func (h *Hash20) Deserialize(r io.Reader) error {
86-
if _, err := r.Read(h[:]); err != nil {
86+
if _, err := io.ReadFull(r, h[:]); err != nil {
8787
return err
8888
}
8989
return nil
@@ -92,7 +92,7 @@ func (h *Hash20) Deserialize(r io.Reader) error {
9292
// Deserialize reads a hash from a reader.
9393
func DeserializeHash20(r io.Reader) (*Hash20, error) {
9494
result := Hash20{}
95-
_, err := r.Read(result[:])
95+
_, err := io.ReadFull(r, result[:])
9696
if err != nil {
9797
return nil, err
9898
}

bitcoin/hash32.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func (h Hash32) Serialize(w io.Writer) error {
9090
}
9191

9292
func (h *Hash32) Deserialize(r io.Reader) error {
93-
if _, err := r.Read(h[:]); err != nil {
93+
if _, err := io.ReadFull(r, h[:]); err != nil {
9494
return err
9595
}
9696
return nil
@@ -99,7 +99,7 @@ func (h *Hash32) Deserialize(r io.Reader) error {
9999
// Deserialize reads a hash from a reader.
100100
func DeserializeHash32(r io.Reader) (*Hash32, error) {
101101
result := Hash32{}
102-
_, err := r.Read(result[:])
102+
_, err := io.ReadFull(r, result[:])
103103
if err != nil {
104104
return nil, err
105105
}

bitcoin/key.go

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,38 @@ func KeyFromStr(s string) (Key, error) {
7070
return Key{}, fmt.Errorf("Key unknown format length %d", len(b))
7171
}
7272

73+
func (k *Key) DecodeString(s string) error {
74+
b, err := decodeAddress(s)
75+
if err != nil {
76+
return err
77+
}
78+
79+
switch b[0] {
80+
case typeMainPrivKey:
81+
k.net = MainNet
82+
case typeTestPrivKey:
83+
k.net = TestNet
84+
default:
85+
return ErrBadKeyType
86+
}
87+
88+
if len(b) == 34 {
89+
if b[len(b)-1] != 0x01 {
90+
return fmt.Errorf("Key not for compressed public : %x", b[len(b)-1:])
91+
}
92+
b = b[1:33]
93+
} else if len(b) == 33 {
94+
b = b[1:]
95+
}
96+
97+
if err := privateKeyIsValid(b); err != nil {
98+
return err
99+
}
100+
101+
k.value.SetBytes(b)
102+
return nil
103+
}
104+
73105
// KeyFromBytes decodes a binary bitcoin key. It returns the key and an error if there was an
74106
// issue.
75107
func KeyFromBytes(b []byte, net Network) (Key, error) {
@@ -130,13 +162,7 @@ func (k Key) Network() Network {
130162

131163
// SetString decodes a key from hex text.
132164
func (k *Key) SetString(s string) error {
133-
nk, err := KeyFromStr(s)
134-
if err != nil {
135-
return err
136-
}
137-
138-
*k = nk
139-
return nil
165+
return k.DecodeString(s)
140166
}
141167

142168
// SetBytes decodes the key from bytes.
@@ -163,7 +189,7 @@ func (k Key) Bytes() []byte {
163189

164190
func (k *Key) Deserialize(r io.Reader) error {
165191
b := make([]byte, 33)
166-
if _, err := r.Read(b); err != nil {
192+
if _, err := io.ReadFull(r, b); err != nil {
167193
return errors.Wrap(err, "key")
168194
}
169195

@@ -213,7 +239,7 @@ func (k Key) MarshalJSON() ([]byte, error) {
213239

214240
// UnmarshalJSON converts from json.
215241
func (k *Key) UnmarshalJSON(data []byte) error {
216-
return k.SetString(string(data[1 : len(data)-1]))
242+
return k.DecodeString(string(data[1 : len(data)-1]))
217243
}
218244

219245
// MarshalText returns the text encoding of the key.
@@ -228,13 +254,7 @@ func (k Key) MarshalText() ([]byte, error) {
228254
// UnmarshalText parses a text encoded key and sets the value of this object.
229255
// Implements encoding.TextUnmarshaler interface.
230256
func (k *Key) UnmarshalText(text []byte) error {
231-
b := make([]byte, hex.DecodedLen(len(text)))
232-
_, err := hex.Decode(b, text)
233-
if err != nil {
234-
return err
235-
}
236-
237-
return k.SetBytes(b)
257+
return k.DecodeString(string(text))
238258
}
239259

240260
// MarshalBinary returns the binary encoding of the key.

bitcoin/lock_script.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -243,21 +243,21 @@ func RawAddressFromLockingScript(lockingScript []byte) (RawAddress, error) {
243243
return RawAddress{}, ErrUnknownScriptTemplate
244244
}
245245

246-
// Parse required signature count
247-
required, length, err := ParsePushNumberScript(script)
248-
if err != nil {
246+
if script[0] != OP_FROMALTSTACK {
249247
return RawAddress{}, ErrUnknownScriptTemplate
250248
}
251-
script = script[length:]
249+
script = script[1:]
252250

253-
if len(script) != 2 {
251+
if len(script) < 2 {
254252
return RawAddress{}, ErrUnknownScriptTemplate
255253
}
256254

257-
if script[0] != OP_FROMALTSTACK {
255+
// Parse required signature count
256+
required, length, err := ParsePushNumberScript(script)
257+
if err != nil {
258258
return RawAddress{}, ErrUnknownScriptTemplate
259259
}
260-
script = script[1:]
260+
script = script[length:]
261261

262262
if script[0] != OP_GREATERTHANOREQUAL {
263263
return RawAddress{}, ErrUnknownScriptTemplate
@@ -381,8 +381,8 @@ func (ra RawAddress) LockingScript() ([]byte, error) {
381381
}
382382

383383
// Check required signature count
384-
result = append(result, PushNumberScript(int64(required))...)
385384
result = append(result, OP_FROMALTSTACK)
385+
result = append(result, PushNumberScript(int64(required))...)
386386
result = append(result, OP_GREATERTHANOREQUAL)
387387
return result, nil
388388
}

0 commit comments

Comments
 (0)