From a0bf2864d243693d79b8a7f1633e54048e8c1fda Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 6 Apr 2021 15:39:27 +0200 Subject: [PATCH] Enable SEP23 parsing for MuxedAccounts (with separated functions) --- xdr/muxed_account.go | 91 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/xdr/muxed_account.go b/xdr/muxed_account.go index 3a9e7c31fa..2b493f4599 100644 --- a/xdr/muxed_account.go +++ b/xdr/muxed_account.go @@ -22,7 +22,7 @@ func MustMuxedAddressPtr(address string) *MuxedAccount { } // SetAddress modifies the receiver, setting it's value to the MuxedAccount form -// of the provided address. +// of the provided G-address. func (m *MuxedAccount) SetAddress(address string) error { if m == nil { return nil @@ -47,6 +47,95 @@ func (m *MuxedAccount) SetAddress(address string) error { } +// SetAddressWithSEP23 modifies the receiver, setting it's value to the MuxedAccount form +// of the provided strkey G-address or M-address, as described in SEP23. +func (m *MuxedAccount) SetAddressWithSEP23(address string) error { + if m == nil { + return nil + } + + switch len(address) { + case 56: + return m.SetAddress(address) + case 69: + raw, err := strkey.Decode(strkey.VersionByteMuxedAccount, address) + if err != nil { + return err + } + if len(raw) != 40 { + return errors.New("invalid muxed address") + } + var muxed MuxedAccountMed25519 + if err = muxed.Id.UnmarshalBinary(raw[:8]); err != nil { + return err + } + copy(muxed.Ed25519[:], raw[8:]) + *m, err = NewMuxedAccount(CryptoKeyTypeKeyTypeMuxedEd25519, muxed) + return err + default: + return errors.New("invalid address") + } + +} + +// SEP23AddressToMuxedAccount returns an MuxedAccount for a given address string +// or SEP23 M-address. +// If the address is not valid the error returned will not be nil +func SEP23AddressToMuxedAccount(address string) (MuxedAccount, error) { + result := MuxedAccount{} + err := result.SetAddressWithSEP23(address) + + return result, err +} + +// Address returns the strkey-encoded form of this MuxedAccount. In particular, it will +// return an M- strkey representation for CryptoKeyTypeKeyTypeMuxedEd25519 variants of the account +// (according to SEP23). This method will panic if the MuxedAccount is backed by a public key of an +// unknown type. +func (m *MuxedAccount) SEP23Address() string { + address, err := m.GetSEP23Address() + if err != nil { + panic(err) + } + return address +} + +// GetAddress returns the strkey-encoded form of this MuxedAccount. In particular, it will +// return an M-strkey representation for CryptoKeyTypeKeyTypeMuxedEd25519 variants of the account +// (according to SEP23). In addition it will return an error if the MuxedAccount is backed by a +// public key of an unknown type. +func (m *MuxedAccount) GetSEP23Address() (string, error) { + if m == nil { + return "", nil + } + + raw := make([]byte, 0, 40) + switch m.Type { + case CryptoKeyTypeKeyTypeEd25519: + ed, ok := m.GetEd25519() + if !ok { + return "", fmt.Errorf("Could not get Ed25519") + } + raw = append(raw, ed[:]...) + return strkey.Encode(strkey.VersionByteAccountID, raw) + case CryptoKeyTypeKeyTypeMuxedEd25519: + ed, ok := m.GetMed25519() + if !ok { + return "", fmt.Errorf("Could not get Med25519") + } + idBytes, err := ed.Id.MarshalBinary() + if err != nil { + return "", fmt.Errorf("Could not marshal ID") + } + raw = append(raw, idBytes...) + raw = append(raw, ed.Ed25519[:]...) + return strkey.Encode(strkey.VersionByteMuxedAccount, raw) + default: + return "", fmt.Errorf("Unknown muxed account type: %v", m.Type) + } + +} + // ToAccountId transforms a MuxedAccount to an AccountId, dropping the // memo Id if necessary func (m MuxedAccount) ToAccountId() AccountId {