Skip to content

Commit e2de07a

Browse files
committed
fix(c32): handle version byte separately
1 parent 10cad8d commit e2de07a

File tree

2 files changed

+18
-14
lines changed

2 files changed

+18
-14
lines changed

pkg/c32/c32.go

+18-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package c32
22

33
import (
4+
"bytes"
45
"crypto/sha256"
56
"errors"
67
"fmt"
@@ -91,40 +92,45 @@ func DecodeC32Address(address string) (version byte, hash160 [20]byte, err error
9192
}
9293

9394
func DecodeWithChecksum(c32addr string) (byte, []byte, error) {
94-
if len(c32addr) < 1 {
95+
if len(c32addr) < 2 {
9596
return 0, nil, errors.New("address too short")
9697
}
9798
if c32addr[0] != 'S' {
9899
return 0, nil, errors.New("address must start with 'S'")
99100
}
100101

101-
c32str := c32addr[1:]
102+
// Extract and decode the version character
103+
versionChar := c32addr[1]
104+
version := byte(strings.IndexRune(crockfordAlphabet, rune(versionChar)))
105+
if version == 255 { // strings.IndexRune returns -1 if not found, which becomes 255 as byte
106+
return 0, nil, errors.New("invalid version character")
107+
}
102108

109+
// Decode the remaining C32 string
110+
c32str := c32addr[2:]
103111
data, err := C32Decode(c32str)
104112
if err != nil {
105113
return 0, nil, err
106114
}
107115

108-
if len(data) != 1+stacks.AddressHashLength+4 {
109-
return 0, nil, fmt.Errorf("invalid decoded length: expected %d, got %d", 1+stacks.AddressHashLength+4, len(data))
116+
// Expected length: data (20 bytes) + checksum (4 bytes)
117+
expectedLength := stacks.AddressHashLength + 4
118+
if len(data) != expectedLength {
119+
return 0, nil, fmt.Errorf("invalid decoded length: expected %d, got %d", expectedLength, len(data))
110120
}
111121

112-
version := data[0]
113-
payload := data[1 : 1+stacks.AddressHashLength]
114-
checksum := data[1+stacks.AddressHashLength:]
122+
payload := data[:stacks.AddressHashLength]
123+
checksum := data[stacks.AddressHashLength:]
115124

116125
// Recompute checksum
117126
versionedData := append([]byte{version}, payload...)
118127
computedChecksum := sha256.Sum256(versionedData)
119128
computedChecksum = sha256.Sum256(computedChecksum[:])
120-
computedChecksum = sha256.Sum256(computedChecksum[:])
121129
computedChecksumBytes := computedChecksum[:4]
122130

123131
// Compare checksums
124-
for i := 0; i < 4; i++ {
125-
if checksum[i] != computedChecksumBytes[i] {
126-
return 0, nil, errors.New("checksum mismatch")
127-
}
132+
if !bytes.Equal(checksum, computedChecksumBytes) {
133+
return 0, nil, errors.New("checksum mismatch")
128134
}
129135

130136
return version, payload, nil

pkg/c32/c32_test.go

-2
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ func TestC32CheckEncodeDecode(t *testing.T) {
100100
t.Fatalf("Failed to serialize address: %v", err)
101101
}
102102

103-
t.Logf("Encoded Address: %s", address)
104-
105103
version, decodedHash, err := DeserializeAddress(address)
106104
if err != nil {
107105
t.Fatalf("Failed to deserialize address: %v", err)

0 commit comments

Comments
 (0)