From 5f48253f59c808f11a59d5ee629f01a97c018b63 Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 4 Apr 2026 18:13:10 +0000 Subject: [PATCH] fix(types): cache address prefix for integrated detection Co-Authored-By: Charon --- types/address.go | 10 +++++----- types/address_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/types/address.go b/types/address.go index aa4feab..755f1ed 100644 --- a/types/address.go +++ b/types/address.go @@ -31,6 +31,7 @@ type Address struct { SpendPublicKey PublicKey ViewPublicKey PublicKey Flags uint8 + prefix uint64 } // IsAuditable reports whether the address has the auditable flag set. @@ -41,11 +42,7 @@ func (a *Address) IsAuditable() bool { // IsIntegrated reports whether the given prefix corresponds to an integrated // address type (standard integrated or auditable integrated). func (a *Address) IsIntegrated() bool { - // This method checks whether the address was decoded with an integrated - // prefix. Since we do not store the prefix in the Address struct, callers - // should use the prefix returned by DecodeAddress to determine this. - // This helper exists for convenience when the prefix is not available. - return false + return IsIntegratedPrefix(a.prefix) } // IsIntegratedPrefix reports whether the given prefix corresponds to an @@ -62,6 +59,8 @@ func IsIntegratedPrefix(prefix uint64) bool { // // The checksum is the first 4 bytes of Keccak-256 over the preceding data. func (a *Address) Encode(prefix uint64) string { + a.prefix = prefix + // Build the raw data: prefix (varint) + keys + flags. prefixBytes := encodeVarint(prefix) raw := make([]byte, 0, len(prefixBytes)+32+32+1+4) @@ -117,6 +116,7 @@ func DecodeAddress(s string) (*Address, uint64, error) { copy(addr.SpendPublicKey[:], remaining[0:32]) copy(addr.ViewPublicKey[:], remaining[32:64]) addr.Flags = remaining[64] + addr.prefix = prefix return addr, prefix, nil } diff --git a/types/address_test.go b/types/address_test.go index df9b404..4745429 100644 --- a/types/address_test.go +++ b/types/address_test.go @@ -65,6 +65,10 @@ func TestAddressEncodeDecodeRoundTrip_Good(t *testing.T) { if decoded.Flags != original.Flags { t.Errorf("Flags mismatch: got 0x%02x, want 0x%02x", decoded.Flags, original.Flags) } + + if decoded.IsIntegrated() != IsIntegratedPrefix(tt.prefix) { + t.Errorf("IsIntegrated mismatch: got %v, want %v", decoded.IsIntegrated(), IsIntegratedPrefix(tt.prefix)) + } }) } } @@ -103,6 +107,29 @@ func TestIsIntegratedPrefix_Good(t *testing.T) { } } +func TestAddressIsIntegrated_Good(t *testing.T) { + tests := []struct { + name string + prefix uint64 + want bool + }{ + {"standard", config.AddressPrefix, false}, + {"integrated", config.IntegratedAddressPrefix, true}, + {"auditable", config.AuditableAddressPrefix, false}, + {"auditable_integrated", config.AuditableIntegratedAddressPrefix, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + addr := makeTestAddress(0) + addr.Encode(tt.prefix) + if got := addr.IsIntegrated(); got != tt.want { + t.Errorf("IsIntegrated: got %v, want %v", got, tt.want) + } + }) + } +} + func TestDecodeAddress_Bad(t *testing.T) { tests := []struct { name string