|
1 | 1 | package c32
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "bytes" |
4 | 5 | "crypto/sha256"
|
5 | 6 | "errors"
|
6 | 7 | "fmt"
|
@@ -91,40 +92,45 @@ func DecodeC32Address(address string) (version byte, hash160 [20]byte, err error
|
91 | 92 | }
|
92 | 93 |
|
93 | 94 | func DecodeWithChecksum(c32addr string) (byte, []byte, error) {
|
94 |
| - if len(c32addr) < 1 { |
| 95 | + if len(c32addr) < 2 { |
95 | 96 | return 0, nil, errors.New("address too short")
|
96 | 97 | }
|
97 | 98 | if c32addr[0] != 'S' {
|
98 | 99 | return 0, nil, errors.New("address must start with 'S'")
|
99 | 100 | }
|
100 | 101 |
|
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 | + } |
102 | 108 |
|
| 109 | + // Decode the remaining C32 string |
| 110 | + c32str := c32addr[2:] |
103 | 111 | data, err := C32Decode(c32str)
|
104 | 112 | if err != nil {
|
105 | 113 | return 0, nil, err
|
106 | 114 | }
|
107 | 115 |
|
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)) |
110 | 120 | }
|
111 | 121 |
|
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:] |
115 | 124 |
|
116 | 125 | // Recompute checksum
|
117 | 126 | versionedData := append([]byte{version}, payload...)
|
118 | 127 | computedChecksum := sha256.Sum256(versionedData)
|
119 | 128 | computedChecksum = sha256.Sum256(computedChecksum[:])
|
120 |
| - computedChecksum = sha256.Sum256(computedChecksum[:]) |
121 | 129 | computedChecksumBytes := computedChecksum[:4]
|
122 | 130 |
|
123 | 131 | // 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") |
128 | 134 | }
|
129 | 135 |
|
130 | 136 | return version, payload, nil
|
|
0 commit comments