Skip to content

Commit 9f9589f

Browse files
authored
fix: handling for long addresses (#520)
Fixes #519
1 parent 96631ad commit 9f9589f

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

ledger/common.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ type Address struct {
213213
networkId uint8
214214
paymentAddress []byte
215215
stakingAddress []byte
216+
extraData []byte
216217
}
217218

218219
// NewAddress returns an Address based on the provided bech32 address string
@@ -236,16 +237,32 @@ func NewAddressFromParts(
236237
networkId uint8,
237238
paymentAddr []byte,
238239
stakingAddr []byte,
239-
) Address {
240+
) (Address, error) {
241+
if len(paymentAddr) != AddressHashSize {
242+
return Address{}, fmt.Errorf("invalid payment address hash length: %d", len(paymentAddr))
243+
}
244+
if len(stakingAddr) > 0 && len(stakingAddr) != AddressHashSize {
245+
return Address{}, fmt.Errorf("invalid staking address hash length: %d", len(stakingAddr))
246+
}
240247
return Address{
241248
addressType: addrType,
242249
networkId: networkId,
243-
paymentAddress: paymentAddr,
244-
stakingAddress: stakingAddr,
245-
}
250+
paymentAddress: paymentAddr[:],
251+
stakingAddress: stakingAddr[:],
252+
}, nil
246253
}
247254

248-
func (a *Address) populateFromBytes(data []byte) {
255+
func (a *Address) populateFromBytes(data []byte) error {
256+
// Check length
257+
dataLen := len(data)
258+
if dataLen < (AddressHashSize + 1) {
259+
return fmt.Errorf("invalid address length: %d", dataLen)
260+
}
261+
if dataLen > (AddressHashSize + 1) {
262+
if dataLen < (AddressHashSize + AddressHashSize + 1) {
263+
return fmt.Errorf("invalid address length: %d", dataLen)
264+
}
265+
}
249266
// Extract header info
250267
header := data[0]
251268
a.addressType = (header & AddressHeaderTypeMask) >> 4
@@ -254,13 +271,22 @@ func (a *Address) populateFromBytes(data []byte) {
254271
// NOTE: this is probably incorrect for Byron
255272
payload := data[1:]
256273
a.paymentAddress = payload[:AddressHashSize]
257-
a.stakingAddress = payload[AddressHashSize:]
274+
if len(payload) > AddressHashSize {
275+
a.stakingAddress = payload[AddressHashSize : AddressHashSize+AddressHashSize]
276+
}
277+
// Store any extra address data
278+
// This is needed to handle the case describe in:
279+
// https://github.com/IntersectMBO/cardano-ledger/issues/2729
280+
if len(payload) > (AddressHashSize + AddressHashSize) {
281+
a.extraData = payload[AddressHashSize+AddressHashSize:]
282+
}
258283
// Adjust stake addresses
259284
if a.addressType == AddressTypeNoneKey ||
260285
a.addressType == AddressTypeNoneScript {
261286
a.stakingAddress = a.paymentAddress[:]
262287
a.paymentAddress = make([]byte, 0)
263288
}
289+
return nil
264290
}
265291

266292
func (a *Address) UnmarshalCBOR(data []byte) error {
@@ -344,6 +370,7 @@ func (a Address) Bytes() []byte {
344370
)
345371
ret = append(ret, a.paymentAddress...)
346372
ret = append(ret, a.stakingAddress...)
373+
ret = append(ret, a.extraData...)
347374
return ret
348375
}
349376

ledger/common_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ func TestAddressFromBytes(t *testing.T) {
133133
addressBytesHex: "61cfe224295a282d69edda5fa8de4f131e2b9cd21a6c9235597fa4ff6b",
134134
expectedAddress: "addr1v887yfpftg5z660dmf063hj0zv0zh8xjrfkfyd2e07j076cecha5k",
135135
},
136+
// Long (but apparently valid) address from:
137+
// https://github.com/IntersectMBO/cardano-ledger/issues/2729
138+
{
139+
addressBytesHex: "015bad085057ac10ecc7060f7ac41edd6f63068d8963ef7d86ca58669e5ecf2d283418a60be5a848a2380eb721000da1e0bbf39733134beca4cb57afb0b35fc89c63061c9914e055001a518c7516",
140+
expectedAddress: "addr1q9d66zzs27kppmx8qc8h43q7m4hkxp5d39377lvxefvxd8j7eukjsdqc5c97t2zg5guqadepqqx6rc9m7wtnxy6tajjvk4a0kze4ljyuvvrpexg5up2sqxj33363v35gtew",
141+
},
136142
}
137143
for _, testDef := range testDefs {
138144
addr := Address{}
@@ -197,12 +203,15 @@ func TestAddressFromParts(t *testing.T) {
197203
},
198204
}
199205
for _, testDef := range testDefs {
200-
addr := NewAddressFromParts(
206+
addr, err := NewAddressFromParts(
201207
testDef.addressType,
202208
testDef.networkId,
203209
testDef.paymentAddr,
204210
testDef.stakingAddr,
205211
)
212+
if err != nil {
213+
t.Fatalf("unexpected error: %s", err)
214+
}
206215
if addr.String() != testDef.expectedAddress {
207216
t.Fatalf(
208217
"address did not match expected value, got: %s, wanted: %s",

0 commit comments

Comments
 (0)