Skip to content

Commit 6e2d59c

Browse files
Merge pull request #13 from tokenized/develop
Develop
2 parents 5f31a32 + 541f46b commit 6e2d59c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+1990
-7835
lines changed

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ tools:
1111
go get golang.org/x/tools/cmd/goimports
1212
go get github.com/golang/lint/golint
1313

14-
test:
15-
go test ./...
14+
prepare:
15+
mkdir -p tmp
16+
17+
test: prepare
18+
go test -coverprofile=tmp/coverage.out ./...
1619

1720
test-race:
1821
go test -race ./...

bitcoin/address.go

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,20 @@ var (
1717
)
1818

1919
const (
20-
AddressTypeMainPKH = 0x00 // Public Key Hash (starts with 1)
21-
AddressTypeMainSH = 0x05 // Script Hash (starts with 3)
22-
AddressTypeMainMultiPKH = 0x76 // Multi-PKH (starts with p) - Experimental value. Not standard
23-
AddressTypeMainRPH = 0x7b // RPH (starts with r) - Experimental value. Not standard
24-
AddressTypeMainPK = 0x06 // Public Key - Experimental value. Not standard
25-
26-
AddressTypeTestPKH = 0x6f // Testnet Public Key Hash (starts with m or n)
27-
AddressTypeTestSH = 0xc4 // Testnet Script Hash (starts with 2)
28-
AddressTypeTestMultiPKH = 0x78 // Multi-PKH (starts with q) - Experimental value. Not standard
29-
AddressTypeTestRPH = 0x7d // RPH (starts with s) - Experimental value. Not standard
30-
AddressTypeTestPK = 0x07 // Public Key - Experimental value. Not standard
20+
AddressTypeMainPKH = 0x00 // Public Key Hash (starts with 1)
21+
AddressTypeMainSH = 0x05 // Script Hash (starts with 3)
22+
AddressTypeMainMultiPKH = 0x76 // Multi-PKH (starts with p) - Experimental value. Not standard
23+
AddressTypeMainRPH = 0x7b // RPH (starts with r) - Experimental value. Not standard
24+
AddressTypeMainPK = 0x06 // Public Key - Experimental value. Not standard
25+
AddressTypeMainNonStandard = 0x08 // Unknown, but possibly spendable locking script
26+
27+
AddressTypeTestPKH = 0x6f // Testnet Public Key Hash (starts with m or n)
28+
AddressTypeTestSH = 0xc4 // Testnet Script Hash (starts with 2)
29+
AddressTypeTestMultiPKH = 0x78 // Multi-PKH (starts with q) - Experimental value. Not standard
30+
AddressTypeTestRPH = 0x7d // RPH (starts with s) - Experimental value. Not standard
31+
AddressTypeTestPK = 0x07 // Public Key - Experimental value. Not standard
32+
AddressTypeTestNonStandard = 0x09 // Unknown, but possibly spendable locking script
33+
3134
)
3235

3336
type Address struct {
@@ -94,6 +97,8 @@ func (a *Address) decodeBytes(b []byte) error {
9497
return nil
9598
case AddressTypeMainRPH:
9699
return a.SetRPH(b[1:], MainNet)
100+
case AddressTypeMainNonStandard:
101+
return a.SetNonStandard(b[1:], MainNet)
97102

98103
// TestNet
99104
case AddressTypeTestPKH:
@@ -129,6 +134,8 @@ func (a *Address) decodeBytes(b []byte) error {
129134
return nil
130135
case AddressTypeTestRPH:
131136
return a.SetRPH(b[1:], TestNet)
137+
case AddressTypeTestNonStandard:
138+
return a.SetNonStandard(b[1:], TestNet)
132139
}
133140

134141
return ErrBadType
@@ -182,6 +189,12 @@ func NewAddressFromRawAddress(ra RawAddress, net Network) Address {
182189
} else {
183190
result.addressType = AddressTypeTestRPH
184191
}
192+
case ScriptTypeNonStandard:
193+
if net == MainNet {
194+
result.addressType = AddressTypeMainNonStandard
195+
} else {
196+
result.addressType = AddressTypeTestNonStandard
197+
}
185198
}
186199

187200
return result
@@ -351,6 +364,28 @@ func (a *Address) SetRPH(rph []byte, net Network) error {
351364
return nil
352365
}
353366

367+
/**************************************** Non-Standard ********************************************/
368+
369+
// NewAddressNonStandard creates an address from a script that is non-standard but possibly
370+
// spendable.
371+
func NewAddressNonStandard(script []byte, net Network) (Address, error) {
372+
var result Address
373+
err := result.SetNonStandard(script, net)
374+
return result, err
375+
}
376+
377+
// SetNonStandard sets the R Puzzle Hash and script type of the address.
378+
func (a *Address) SetNonStandard(script []byte, net Network) error {
379+
if net == MainNet {
380+
a.addressType = AddressTypeMainNonStandard
381+
} else {
382+
a.addressType = AddressTypeTestNonStandard
383+
}
384+
385+
a.data = script
386+
return nil
387+
}
388+
354389
/***************************************** Common *************************************************/
355390

356391
func (a Address) Type() byte {
@@ -365,13 +400,8 @@ func (a Address) String() string {
365400
// Network returns the network id for the address.
366401
func (a Address) Network() Network {
367402
switch a.addressType {
368-
case AddressTypeMainPKH:
369-
fallthrough
370-
case AddressTypeMainSH:
371-
fallthrough
372-
case AddressTypeMainMultiPKH:
373-
fallthrough
374-
case AddressTypeMainRPH:
403+
case AddressTypeMainPKH, AddressTypeMainSH, AddressTypeMainMultiPKH, AddressTypeMainRPH,
404+
AddressTypeMainNonStandard:
375405
return MainNet
376406
}
377407
return TestNet
@@ -385,25 +415,11 @@ func (a Address) IsEmpty() bool {
385415
// Hash returns the hash corresponding to the address.
386416
func (a Address) Hash() (*Hash20, error) {
387417
switch a.addressType {
388-
case AddressTypeMainPKH:
389-
fallthrough
390-
case AddressTypeTestPKH:
391-
fallthrough
392-
case AddressTypeMainSH:
393-
fallthrough
394-
case AddressTypeTestSH:
395-
fallthrough
396-
case AddressTypeMainRPH:
397-
fallthrough
398-
case AddressTypeTestRPH:
418+
case AddressTypeMainPKH, AddressTypeTestPKH, AddressTypeMainSH, AddressTypeTestSH,
419+
AddressTypeMainRPH, AddressTypeTestRPH:
399420
return NewHash20(a.data)
400-
case AddressTypeMainPK:
401-
fallthrough
402-
case AddressTypeTestPK:
403-
fallthrough
404-
case AddressTypeMainMultiPKH:
405-
fallthrough
406-
case AddressTypeTestMultiPKH:
421+
case AddressTypeMainPK, AddressTypeTestPK, AddressTypeMainMultiPKH, AddressTypeTestMultiPKH,
422+
AddressTypeMainNonStandard, AddressTypeTestNonStandard:
407423
return NewHash20(Hash160(a.data))
408424
}
409425
return nil, ErrUnknownScriptTemplate

bitcoin/encode.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,21 +217,31 @@ func ReadBase128VarInt(r io.Reader) (uint64, error) {
217217
return value, nil
218218
}
219219

220+
const bitLeast7EmptyMask = 0xffffff80
221+
const bit8thMask = 0x80
222+
const bitLeast7Mask = 0x0000007f
223+
220224
func WriteBase128VarInt(w io.Writer, value uint64) error {
221-
v := value
222225
for {
223-
if v < 128 {
224-
var b [1]byte
225-
b[0] = byte(v)
226-
_, err := w.Write(b[:])
226+
if value&bitLeast7EmptyMask == 0 {
227+
b := []byte{byte(value)}
228+
_, err := w.Write(b)
227229
return err
228230
}
229231

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 {
232+
subValue := []byte{(byte(value&bitLeast7Mask) | bit8thMask)} // Get last 7 bits and set high bit
233+
if _, err := w.Write(subValue); err != nil {
233234
return err
234235
}
235-
v = v >> 7
236+
value = value >> 7
236237
}
237238
}
239+
240+
func ReadBase128VarSignedInt(r io.Reader) (int64, error) {
241+
result, err := ReadBase128VarInt(r)
242+
return int64(result), err
243+
}
244+
245+
func WriteBase128VarSignedInt(w io.Writer, value int64) error {
246+
return WriteBase128VarInt(w, uint64(value))
247+
}

bitcoin/encode_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package bitcoin
33
import (
44
"bytes"
55
"encoding/hex"
6+
"fmt"
67
"testing"
78
)
89

@@ -31,6 +32,10 @@ func TestBase128(t *testing.T) {
3132
hex: "ff01",
3233
value: 255,
3334
},
35+
{
36+
hex: "AC02",
37+
value: 300,
38+
},
3439
}
3540

3641
for _, tt := range tests {
@@ -60,3 +65,61 @@ func TestBase128(t *testing.T) {
6065
})
6166
}
6267
}
68+
69+
func TestBase128Signed(t *testing.T) {
70+
tests := []struct {
71+
hex string
72+
value int64
73+
}{
74+
{
75+
hex: "b0b8d0a2a4b081a316",
76+
value: 1604976374254410800,
77+
},
78+
{
79+
hex: "00",
80+
value: 0,
81+
},
82+
{
83+
hex: "01",
84+
value: 1,
85+
},
86+
{
87+
hex: "0f",
88+
value: 15,
89+
},
90+
{
91+
hex: "ff01",
92+
value: 255,
93+
},
94+
{
95+
hex: "ac02",
96+
value: 300,
97+
},
98+
{
99+
hex: "ac02",
100+
value: -300,
101+
},
102+
}
103+
104+
for _, tt := range tests {
105+
t.Run(tt.hex, func(t *testing.T) {
106+
var w bytes.Buffer
107+
if err := WriteBase128VarSignedInt(&w, tt.value); err != nil {
108+
t.Fatalf("Failed to write : %s", err)
109+
}
110+
111+
fmt.Printf("Bytes : %x\n", w.Bytes())
112+
113+
value, err := ReadBase128VarSignedInt(&w)
114+
if err != nil {
115+
t.Fatalf("Failed to read : %s", err)
116+
}
117+
118+
if value != tt.value {
119+
t.Errorf("Wrong value : got %d, want %d", value, tt.value)
120+
}
121+
122+
t.Logf("Value : %d", value)
123+
})
124+
}
125+
}

bitcoin/hash20.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@ package bitcoin
33
import (
44
"bytes"
55
"encoding/hex"
6-
"errors"
76
"fmt"
87
"io"
8+
9+
"github.com/pkg/errors"
10+
)
11+
12+
var (
13+
ErrWrongSize = errors.New("Wrong size")
914
)
1015

1116
const Hash20Size = 20
@@ -15,7 +20,7 @@ type Hash20 [Hash20Size]byte
1520

1621
func NewHash20(b []byte) (*Hash20, error) {
1722
if len(b) != Hash20Size {
18-
return nil, errors.New("Wrong byte length")
23+
return nil, errors.Wrapf(ErrWrongSize, "got %d, want %d", len(b), Hash20Size)
1924
}
2025
result := Hash20{}
2126
copy(result[:], b)
@@ -25,7 +30,7 @@ func NewHash20(b []byte) (*Hash20, error) {
2530
// NewHash20FromStr creates a little endian hash from a big endian string.
2631
func NewHash20FromStr(s string) (*Hash20, error) {
2732
if len(s) != 2*Hash20Size {
28-
return nil, fmt.Errorf("Wrong size hex for Hash20 : %d", len(s))
33+
return nil, errors.Wrapf(ErrWrongSize, "hex: got %d, want %d", len(s), Hash20Size*2)
2934
}
3035

3136
b := make([]byte, Hash20Size)
@@ -52,7 +57,7 @@ func (h Hash20) Bytes() []byte {
5257
// SetBytes sets the value of the hash.
5358
func (h *Hash20) SetBytes(b []byte) error {
5459
if len(b) != Hash20Size {
55-
return errors.New("Wrong byte length")
60+
return errors.Wrapf(ErrWrongSize, "got %d, want %d", len(b), Hash20Size)
5661
}
5762
copy(h[:], b)
5863
return nil
@@ -76,6 +81,11 @@ func (h *Hash20) Equal(o *Hash20) bool {
7681
return bytes.Equal(h[:], o[:])
7782
}
7883

84+
func (h Hash20) IsZero() bool {
85+
var zero Hash20 // automatically initializes to zero
86+
return h.Equal(&zero)
87+
}
88+
7989
// Serialize writes the hash into a writer.
8090
func (h Hash20) Serialize(w io.Writer) error {
8191
_, err := w.Write(h[:])

bitcoin/hash32.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ package bitcoin
33
import (
44
"bytes"
55
"encoding/hex"
6-
"errors"
76
"fmt"
87
"io"
8+
9+
"github.com/pkg/errors"
910
)
1011

1112
const Hash32Size = 32
@@ -15,7 +16,7 @@ type Hash32 [Hash32Size]byte
1516

1617
func NewHash32(b []byte) (*Hash32, error) {
1718
if len(b) != Hash32Size {
18-
return nil, errors.New("Wrong byte length")
19+
return nil, errors.Wrapf(ErrWrongSize, "got %d, want %d", len(b), Hash32Size)
1920
}
2021
result := Hash32{}
2122
copy(result[:], b)
@@ -25,7 +26,7 @@ func NewHash32(b []byte) (*Hash32, error) {
2526
// NewHash32FromStr creates a little endian hash from a big endian string.
2627
func NewHash32FromStr(s string) (*Hash32, error) {
2728
if len(s) != 2*Hash32Size {
28-
return nil, fmt.Errorf("Wrong size hex for Hash32 : %d", len(s))
29+
return nil, errors.Wrapf(ErrWrongSize, "hex: got %d, want %d", len(s), Hash32Size*2)
2930
}
3031

3132
b := make([]byte, Hash32Size)
@@ -59,7 +60,7 @@ func (h Hash32) Bytes() []byte {
5960
// SetBytes sets the value of the hash.
6061
func (h *Hash32) SetBytes(b []byte) error {
6162
if len(b) != Hash32Size {
62-
return errors.New("Wrong byte length")
63+
return errors.Wrapf(ErrWrongSize, "got %d, want %d", len(b), Hash32Size)
6364
}
6465
copy(h[:], b)
6566
return nil
@@ -83,6 +84,11 @@ func (h *Hash32) Equal(o *Hash32) bool {
8384
return bytes.Equal(h[:], o[:])
8485
}
8586

87+
func (h Hash32) IsZero() bool {
88+
var zero Hash32 // automatically initializes to zero
89+
return h.Equal(&zero)
90+
}
91+
8692
// Serialize writes the hash into a writer.
8793
func (h Hash32) Serialize(w io.Writer) error {
8894
_, err := w.Write(h[:])

bitcoin/key.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ func GenerateKey(net Network) (Key, error) {
137137
return Key{net: net, value: *key.D}, nil
138138
}
139139

140+
func (k Key) Equal(other Key) bool {
141+
if k.net != other.net {
142+
return false
143+
}
144+
145+
return k.value.Cmp(&other.value) == 0
146+
}
147+
140148
// String returns the type followed by the key data with a checksum, encoded with Base58.
141149
func (k Key) String() string {
142150
var keyType byte

0 commit comments

Comments
 (0)