From 72b9479ffa03db88a9ae4374a3b39de72ca55c60 Mon Sep 17 00:00:00 2001 From: Denis Subbotin Date: Fri, 22 Dec 2023 21:36:11 +0300 Subject: [PATCH] fix accountID parser --- ton/account.go | 26 +++++++++++++----- ton/account_test.go | 65 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/ton/account.go b/ton/account.go index 98920bfa..eeb2fdd6 100644 --- a/ton/account.go +++ b/ton/account.go @@ -3,9 +3,11 @@ package ton import ( "encoding/base64" "encoding/binary" + "encoding/hex" "encoding/json" "fmt" "io" + "strconv" "strings" "github.com/snksoft/crc" @@ -125,19 +127,29 @@ func AccountIDFromBase64Url(s string) (AccountID, error) { } func AccountIDFromRaw(s string) (AccountID, error) { - var ( - workchain int32 - address []byte - aa AccountID - ) - _, err := fmt.Sscanf(s, "%d:%x", &workchain, &address) + var aa AccountID + + colon := strings.IndexByte(s, ':') + if colon == -1 { + return AccountID{}, fmt.Errorf("invalid account id format") + } + if len(s)-colon-1 < 64 { + fmt.Println(s) + s = s[:colon] + ":" + strings.Repeat("0", 64-len(s)+colon+1) + s[colon+1:] + fmt.Println(s) + } + w, err := strconv.ParseInt(s[:colon], 10, 32) + if err != nil { + return AccountID{}, err + } + address, err := hex.DecodeString(s[colon+1:]) if err != nil { return AccountID{}, err } if len(address) != 32 { return AccountID{}, fmt.Errorf("address len must be 32 bytes") } - aa.Workchain = workchain + aa.Workchain = int32(w) copy(aa.Address[:], address) return aa, nil } diff --git a/ton/account_test.go b/ton/account_test.go index c759b83c..ecd0051e 100644 --- a/ton/account_test.go +++ b/ton/account_test.go @@ -24,6 +24,71 @@ func TestAccountIDJsonUnmarshal(t *testing.T) { } } +func TestParseRawAccountID(t *testing.T) { + cases := []struct { + name string + input string + output string + success bool + }{ + { + name: "master", + input: "-1:7014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + output: "-1:7014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + success: true, + }, + { + name: "base", + input: "0:7014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + output: "0:7014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + success: true, + }, + { + name: "upper case", + input: "0:7014A79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + output: "0:7014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + success: true, + }, + { + name: "zfill1", + input: "0:014A79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + output: "0:0014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + success: true, + }, + { + name: "zfill2", + input: "0:14A79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + output: "0:0014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + success: true, + }, + { + name: "invalid", + input: "0:14A79eb7a8ZZZZ", + output: "0:0014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + success: false, + }, + { + name: "invalid2", + input: "0:7014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e:", + output: "0:7014a79eb7a81cf37542a62b75defa99427580e6612f956d47caa0fe0ec5d05e", + success: false, + }, + } + + for i := range cases { + c := cases[i] + t.Run(c.name, func(t *testing.T) { + a, err := AccountIDFromRaw(c.input) + if (err == nil) != c.success { + t.Fatal(err) + } + if c.success && a.ToRaw() != c.output { + t.Fatal(a.ToRaw()) + } + }) + } +} + func TestToMsgAddress(t *testing.T) { ma := (*AccountID)(nil).ToMsgAddress() if ma.SumType != "AddrNone" {