diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6f4785e7ed4fc39fd98959cdc061b098caa5f4bf..366b0a914049071de28e752cc340f322243f7b34 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,25 +14,29 @@ before_script: - mkdir -p ~/.ssh - chmod 700 ~/.ssh - ssh-keyscan -t rsa $GITLAB_SERVER > ~/.ssh/known_hosts + - rm -rf ~/.gitconfig - git config --global url."git@$GITLAB_SERVER:".insteadOf "https://gitlab.com/" - git config --global url."git@$GITLAB_SERVER:".insteadOf "https://git.xx.network/" --add - export PATH=$HOME/go/bin:$PATH stages: + - test - build - trigger_integration -build: - stage: build +test: + stage: test image: $DOCKER_IMAGE script: - git clean -ffdx - go mod vendor -v - - go build ./... - go mod tidy - + - go build ./... - mkdir -p testdata + + # Test coverage - go-acc --covermode atomic --output testdata/coverage.out ./... -- -v + # Exclude some specific packages and files - cat testdata/coverage.out | grep -v pb[.]go > testdata/coverage-real.out - go tool cover -func=testdata/coverage-real.out - go tool cover -html=testdata/coverage-real.out -o testdata/coverage.html @@ -41,15 +45,25 @@ build: - go tool cover -func=testdata/coverage-real.out | grep "total:" | awk '{print $3}' | sed 's/\%//g' > testdata/coverage-percentage.txt - export CODE_CHECK=$(echo "$(cat testdata/coverage-percentage.txt) >= $MIN_CODE_COVERAGE" | bc -l) - (if [ "$CODE_CHECK" == "1" ]; then echo "Minimum coverage of $MIN_CODE_COVERAGE succeeded"; else echo "Minimum coverage of $MIN_CODE_COVERAGE failed"; exit 1; fi); + artifacts: + paths: + - vendor/ + - testdata/ + +build: + stage: build + image: $DOCKER_IMAGE + script: + - go mod vendor -v + - go build ./... - mkdir -p release - GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags '-w -s' ./... - cd release artifacts: paths: - - vendor/ - - testdata/ - release/ + trigger-integration: stage: trigger_integration trigger: diff --git a/Makefile b/Makefile index 617caf39fb466279f636b39923aedd9aee036463..53618bfb42c37e16bffa8b8554700c2507ca55eb 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,21 @@ .PHONY: update master release update_master update_release build clean -setup: - git config --global --add url."git@gitlab.com:".insteadOf "https://gitlab.com/" - clean: - rm -rf vendor/ - go mod vendor + go mod tidy + go mod vendor -e update: -GOFLAGS="" go get all build: go build ./... - go mod tidy update_release: - GOFLAGS="" go get -u gitlab.com/xx_network/primitives@release + GOFLAGS="" go get gitlab.com/xx_network/primitives@release update_master: - GOFLAGS="" go get -u gitlab.com/xx_network/primitives@master + GOFLAGS="" go get gitlab.com/xx_network/primitives@master master: update_master clean build -release: update_release clean build +release: update_release clean build diff --git a/authorizer/dns.go b/authorizer/dns.go index d7c3ded08014b3ca0647ce556190f0c342c667a9..c5ea47f58409224b9f36b458c0cf0ae604979945 100644 --- a/authorizer/dns.go +++ b/authorizer/dns.go @@ -9,7 +9,6 @@ package authorizer import ( "encoding/hex" - "fmt" ) const ( @@ -32,5 +31,5 @@ func GetGatewayDns(gwID []byte) string { if len(encoded) > maxGwIdLength { encoded = encoded[:maxGwIdLength] } - return fmt.Sprintf("%s.%s", encoded, DomainName) + return encoded + "." + DomainName } diff --git a/current/activity.go b/current/activity.go index dbeaf23c77dfe99b9a2d22349e1fe77409142ebf..d53ce8f01a45c1c802e5a4e9b4ce18e5370f8dbd 100644 --- a/current/activity.go +++ b/current/activity.go @@ -8,7 +8,7 @@ package current import ( - "fmt" + "strconv" "github.com/pkg/errors" @@ -55,7 +55,7 @@ func (a Activity) String() string { case CRASH: return "CRASH" default: - return fmt.Sprintf("UNKNOWN STATE: %d", a) + return "UNKNOWN ACTIVITY: " + strconv.FormatUint(uint64(a), 10) } } @@ -78,6 +78,6 @@ func (a Activity) ConvertToRoundState() (states.Round, error) { default: // Unsupported conversion. Return an arbitrary round and error return states.Round(99), errors.Errorf( - "unable to convert activity %+v to valid state", a) + "unable to convert activity %s (%d) to a valid state", a, a) } } diff --git a/current/activity_test.go b/current/activity_test.go index f4884090a7ce250fc8c061a7d86e7a43993e571c..9759b1fe2938ae5547694ec7989fa75c4e500e47 100644 --- a/current/activity_test.go +++ b/current/activity_test.go @@ -18,7 +18,7 @@ import ( // Consistency test of Activity.String. func TestActivity_String(t *testing.T) { expected := []string{"NOT_STARTED", "WAITING", "PRECOMPUTING", "STANDBY", - "REALTIME", "COMPLETED", "ERROR", "CRASH", "UNKNOWN STATE: 8"} + "REALTIME", "COMPLETED", "ERROR", "CRASH", "UNKNOWN ACTIVITY: 8"} for st := NOT_STARTED; st <= NUM_STATES; st++ { if st.String() != expected[st] { diff --git a/fact/fact.go b/fact/fact.go index d8e5a117f6ba9920434a33129637bcec81ec354f..b9592c189b734383b64ae1a5f28749f131c3d8dc 100644 --- a/fact/fact.go +++ b/fact/fact.go @@ -42,7 +42,7 @@ type Fact struct { // validation error. func NewFact(ft FactType, fact string) (Fact, error) { if len(fact) > maxFactLen { - return Fact{}, errors.Errorf("Fact (%s) exceeds maximum character limit"+ + return Fact{}, errors.Errorf("Fact (%s) exceeds maximum character limit " + "for a fact (%d characters)", fact, maxFactLen) } @@ -71,7 +71,7 @@ func UnstringifyFact(s string) (Fact, error) { } if len(s) > maxFactLen { - return Fact{}, errors.Errorf("Fact (%s) exceeds maximum character limit"+ + return Fact{}, errors.Errorf("Fact (%s) exceeds maximum character limit " + "for a fact (%d characters)", s, maxFactLen) } @@ -111,7 +111,7 @@ func ValidateFact(fact Fact) error { case Nickname: return validateNickname(fact.Fact) default: - return errors.Errorf("Unknown fact type: %v", fact.T) + return errors.Errorf("Unknown fact type: %d", fact.T) } } @@ -130,8 +130,7 @@ func extractNumberInfo(fact string) (number, countryCode string) { func validateEmail(email string) error { // Check that the input is validly formatted if err := checkmail.ValidateFormat(email); err != nil { - return errors.Errorf( - "Could not validate format for email [%s]: %v", email, err) + return errors.Wrapf(err, "Could not validate format for email %q", email) } return nil @@ -140,30 +139,32 @@ func validateEmail(email string) error { // Checks if the number and country code passed in is parse-able // and is a valid phone number with that information func validateNumber(number, countryCode string) error { - errCh := make(chan error) - - go func() { + catchPanic := func(number, countryCode string) (err error) { defer func() { if r := recover(); r != nil { - errCh <- errors.Errorf("Crash occured on phone "+ - "validation of: number: %s, country code: %s", number, - countryCode) + err = errors.Errorf("Crash occured on phone validation of: "+ + "number: %s, country code: %s: %+v", number, countryCode, r) } }() if len(number) == 0 || len(countryCode) == 0 { - errCh <- errors.New("Number or input are of length 0") + err = errors.New("Number or input are of length 0") + return err } num, err := libphonenumber.Parse(number, countryCode) if err != nil || num == nil { - errCh <- errors.Errorf("Could not parse number [%s]: %v", number, err) + err = errors.Wrapf(err, "Could not parse number %q", number) + return err } if !libphonenumber.IsValidNumber(num) { - errCh <- errors.Errorf("Could not validate number [%s]: %v", number, err) + err = errors.Errorf("Could not validate number %q", number) + return err } - errCh <- nil - }() - return <-errCh + + return nil + } + + return catchPanic(number, countryCode) } func validateNickname(nickname string) error { diff --git a/fact/factList.go b/fact/factList.go index 897a255b0601ee2efc0105e25cd7a4a8feeeb33a..8057efc0853af2355d662119c09e4e4bd60c3ae3 100644 --- a/fact/factList.go +++ b/fact/factList.go @@ -37,14 +37,17 @@ func UnstringifyFactList(s string) (FactList, string, error) { parts := strings.SplitN(s, factBreak, 2) if len(parts) != 2 { return nil, "", errors.New("Invalid fact string passed") + } else if parts[0] == "" { + return nil, parts[1], nil } factStrings := strings.Split(parts[0], factDelimiter) - var factList []Fact + factList := make([]Fact, 0, len(factStrings)) for _, fString := range factStrings { fact, err := UnstringifyFact(fString) if err != nil { - jww.WARN.Printf("Fact failed to unstringify, dropped: %s", err) + jww.WARN.Printf( + "Fact %q failed to unstringify, dropped: %s", fString, err) } else { factList = append(factList, fact) } diff --git a/fact/factList_test.go b/fact/factList_test.go index 9c4897c695fe706d45f3e1667f3b369e1e849da0..b40dd39aa1892dfe3869b7e4bccb98edbde9b530 100644 --- a/fact/factList_test.go +++ b/fact/factList_test.go @@ -35,6 +35,23 @@ func TestFactList_Stringify_UnstringifyFactList(t *testing.T) { } } +// Tests that a nil FactList marshalled by FactList.Stringify and unmarshalled +// by UnstringifyFactList matches the original. +func TestUnstringifyFactList_NilFactList(t *testing.T) { + var expected FactList + + flString := expected.Stringify() + factList, _, err := UnstringifyFactList(flString) + if err != nil { + t.Fatalf("Failed to unstringify %q: %+v", flString, err) + } + + if !reflect.DeepEqual(factList, expected) { + t.Errorf("Unexpected unstringified FactList."+ + "\nexpected: %v\nreceived: %v", expected, factList) + } +} + // Error path: Tests that UnstringifyFactList returns an error for a malformed // stringified FactList. func Test_UnstringifyFactList_MissingFactBreakError(t *testing.T) { diff --git a/fact/fact_test.go b/fact/fact_test.go index 449261b199bfb32f43215bdb45ef181545542024..11a67d17449f3d54d2e5e49d4ae39c803e1dc424 100644 --- a/fact/fact_test.go +++ b/fact/fact_test.go @@ -139,7 +139,7 @@ func TestUnstringifyFact_Error(t *testing.T) { expectedErr string }{ {"", "stringified facts must at least have a type at the start"}, - {longFact, fmt.Sprintf("Fact (%s) exceeds maximum character limitfor "+ + {longFact, fmt.Sprintf("Fact (%s) exceeds maximum character limit for "+ "a fact (%d characters)", longFact, maxFactLen)}, {"P", "stringified facts must be at least 1 character long"}, {"QA", `Failed to unstringify fact type for "QA"`}, @@ -221,8 +221,8 @@ func Test_validateNumber_Error(t *testing.T) { {"5", "", "Number or input are of length 0"}, {"", "US", "Number or input are of length 0"}, // {"020 8743 8000135", "UK", `Could not parse number "020 8743 8000135"`}, - {"8005559486", "UK", `Could not parse number [8005559486]`}, - {"+343511234567", "ES", `Could not validate number [+343511234567]`}, + {"8005559486", "UK", `Could not parse number "8005559486"`}, + {"+343511234567", "ES", `Could not validate number "+343511234567"`}, } for i, tt := range tests { diff --git a/fact/type.go b/fact/type.go index 1ba30054e09cf17c5bb1ff7090e86f4521377fb0..68501213187e33e5284725319c1b5dc841b402a2 100644 --- a/fact/type.go +++ b/fact/type.go @@ -8,7 +8,7 @@ package fact import ( - "fmt" + "strconv" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" @@ -36,7 +36,7 @@ func (t FactType) String() string { case Nickname: return "Nickname" default: - return fmt.Sprintf("Unknown Fact FactType: %d", t) + return "Unknown Fact FactType: " + strconv.FormatUint(uint64(t), 10) } } @@ -68,10 +68,15 @@ func UnstringifyFactType(s string) (FactType, error) { case "N": return Nickname, nil } - return 3, errors.Errorf("Unknown Fact FactType: %s", s) + return 99, errors.Errorf("Unknown Fact FactType: %s", s) } // IsValid determines if the FactType is one of the defined types. func (t FactType) IsValid() bool { - return t == Username || t == Email || t == Phone || t == Nickname + switch t { + case Username, Email, Phone, Nickname: + return true + default: + return false + } } diff --git a/format/fingerprint.go b/format/fingerprint.go index 884f6bc0d1d5fee697048e3b75da962a3b506b46..f567005e1ffeaae43506ef801ffd6c2ebac7cf05 100644 --- a/format/fingerprint.go +++ b/format/fingerprint.go @@ -9,6 +9,9 @@ package format import ( "encoding/base64" + "encoding/json" + + "github.com/pkg/errors" ) type Fingerprint [KeyFPLen]byte @@ -30,3 +33,25 @@ func (fp Fingerprint) Bytes() []byte { func (fp Fingerprint) String() string { return base64.StdEncoding.EncodeToString(fp.Bytes()) } + +// MarshalJSON adheres to the json.Marshaler interface. +func (fp Fingerprint) MarshalJSON() ([]byte, error) { + return json.Marshal(fp[:]) +} + +// UnmarshalJSON adheres to the json.Unmarshaler interface. +func (fp *Fingerprint) UnmarshalJSON(data []byte) error { + var fpBytes []byte + err := json.Unmarshal(data, &fpBytes) + if err != nil { + return err + } + + if len(fpBytes) != KeyFPLen { + return errors.Errorf("length of fingerprint must be %d", KeyFPLen) + } + + copy(fp[:], fpBytes[:]) + + return nil +} diff --git a/format/fingerprint_test.go b/format/fingerprint_test.go index 1e10e80ac808d82872fbc6c96a21ac678754a107..c625515359e0b507b6c745dde43ef0f2b0e67625 100644 --- a/format/fingerprint_test.go +++ b/format/fingerprint_test.go @@ -10,6 +10,7 @@ package format import ( "bytes" "encoding/base64" + "encoding/json" "math/rand" "testing" ) @@ -66,3 +67,26 @@ func TestFingerprint_String(t *testing.T) { "\nexpected: %s\nreceived: %s", expectedString, fp.String()) } } + +func Test_Fingerprint_JSON_Marshal_Unmarshal(t *testing.T) { + prng := rand.New(rand.NewSource(74043)) + fpBytes := make([]byte, KeyFPLen) + prng.Read(fpBytes) + + expected := NewFingerprint(fpBytes) + + data, err := json.Marshal(expected) + if err != nil { + t.Errorf("Failed to marshal %T: %+v", expected, err) + } + + var fp Fingerprint + if err = json.Unmarshal(data, &fp); err != nil { + t.Errorf("Failed to unmarshal %T: %+v", fp, err) + } + + if expected != fp { + t.Errorf("Unexpected fingerprint.\nexpected: %s\nreceived: %s", + expected, fp) + } +} diff --git a/go.mod b/go.mod index ac1188b2f7eafa1f85fa7b53b5bf9e6f63b22de8..4e5ec0c2411d49b4e120c296bdb1e6bf69f38be6 100644 --- a/go.mod +++ b/go.mod @@ -8,15 +8,13 @@ require ( github.com/pkg/errors v0.9.1 github.com/spf13/jwalterweatherman v1.1.0 github.com/ttacon/libphonenumber v1.2.1 - gitlab.com/xx_network/primitives v0.0.4-0.20230203173415-81c2cb07da44 - golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad + gitlab.com/xx_network/primitives v0.0.4-0.20230724185812-bc6fc6e5341b + golang.org/x/crypto v0.5.0 ) require ( github.com/golang/protobuf v1.5.2 // indirect - github.com/stretchr/testify v1.6.1 // indirect github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect - golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 // indirect + golang.org/x/sys v0.10.0 // indirect google.golang.org/protobuf v1.26.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect ) diff --git a/go.sum b/go.sum index de5165c3854b38f978ed2c5f912e2a0ef899cd29..3a5c28dc4197a8e12be2fa981f69e43be6d98343 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,5 @@ github.com/badoux/checkmail v1.2.1 h1:TzwYx5pnsV6anJweMx2auXdekBwGr/yt1GgalIx9nBQ= github.com/badoux/checkmail v1.2.1/go.mod h1:XroCOBU5zzZJcLvgwU15I+2xXyCdTWXyR9MGfRhBYy0= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4= @@ -16,32 +15,21 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 h1:5u+EJUQiosu3JFX0XS0qTf5FznsMOzTjGqavBGuCbo0= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2/go.mod h1:4kyMkleCiLkgY6z8gK5BkI01ChBtxR0ro3I1ZDcGM3w= github.com/ttacon/libphonenumber v1.2.1 h1:fzOfY5zUADkCkbIafAed11gL1sW+bJ26p6zWLBMElR4= github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M= -gitlab.com/xx_network/primitives v0.0.4-0.20230203173415-81c2cb07da44 h1:vNm76SCeKZiCaVL0rCIcqDxMzSVL50g3XO6dQYN8r3Q= -gitlab.com/xx_network/primitives v0.0.4-0.20230203173415-81c2cb07da44/go.mod h1:wUxbEBGOBJZ/RkAiVAltlC1uIlIrU0dE113Nq7HiOhw= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gitlab.com/xx_network/primitives v0.0.4-0.20230724185812-bc6fc6e5341b h1:oymmRpA+5/SeBp+MgFeYyuB8S9agfetGDnxBXXq9utE= +gitlab.com/xx_network/primitives v0.0.4-0.20230724185812-bc6fc6e5341b/go.mod h1:vI6JXexgqihcIVFGsZAwGlHWGT14XC24NwEB2c6q9nc= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/knownRounds/knownRounds.go b/knownRounds/knownRounds.go index f8b25a115fb14e615a26af33a7addfedcb6e1d0b..aba5f1aa066cc9675bff9161569ee431615814e3 100644 --- a/knownRounds/knownRounds.go +++ b/knownRounds/knownRounds.go @@ -291,7 +291,7 @@ func (kr *KnownRounds) Forward(rid id.Round) { // unknown and ending with func (kr *KnownRounds) RangeUnchecked(oldestUnknown id.Round, threshold uint, roundCheck func(id id.Round) bool, maxPickups int) ( - id.Round, []id.Round, []id.Round) { + earliestRound id.Round, has, unknown []id.Round) { newestRound := kr.lastChecked @@ -303,10 +303,8 @@ func (kr *KnownRounds) RangeUnchecked(oldestUnknown id.Round, threshold uint, oldestPossibleEarliestRound = newestRound - id.Round(threshold) } - earliestRound := kr.lastChecked + 1 - var unknown []id.Round - - has := make([]id.Round, 0, maxPickups) + earliestRound = kr.lastChecked + 1 + has = make([]id.Round, 0, maxPickups) // If the oldest unknown round is outside the range we are attempting to // check, then skip checking @@ -368,16 +366,9 @@ func (kr *KnownRounds) RangeUncheckedMaskedRange(mask *KnownRounds, numChecked := 0 if mask.firstUnchecked != mask.lastChecked { - jww.TRACE.Printf("mask (before Forward()) {\n\tbitStream: %064b\n\tfirstUnchecked: %d\n\tlastChecked: %d\n\tfuPos: %d\n}", mask.bitStream, mask.firstUnchecked, mask.lastChecked, mask.fuPos) mask.Forward(kr.firstUnchecked) subSample, delta := kr.subSample(mask.firstUnchecked, mask.lastChecked) // FIXME: it is inefficient to make a copy of the mask here. - - jww.TRACE.Printf("mask (after Forward()) {\n\tbitStream: %064b\n\tfirstUnchecked: %d\n\tlastChecked: %d\n\tfuPos: %d\n}", mask.bitStream, mask.firstUnchecked, mask.lastChecked, mask.fuPos) - jww.TRACE.Printf("kr {\n\tbitStream: %064b\n\tfirstUnchecked: %d\n\tlastChecked: %d\n\tfuPos: %d\n}", kr.bitStream, kr.firstUnchecked, kr.lastChecked, kr.fuPos) - jww.TRACE.Printf("delta: %d", delta) - jww.TRACE.Printf("subSample: %064b", subSample) - // jww.TRACE.Printf("maskSubSample: %064b", maskSubSample) result := subSample.implies(mask.bitStream) for i := mask.firstUnchecked + id.Round(delta) - 1; i >= mask.firstUnchecked && numChecked < maxChecked; i, numChecked = i-1, numChecked+1 { diff --git a/nicknames/isValid.go b/nicknames/isValid.go index 2c6244d8acb40cf055e2e7877f1675f8a03d7dad..b412c46653134368af72a6316ca58ebfd66cf461 100644 --- a/nicknames/isValid.go +++ b/nicknames/isValid.go @@ -27,7 +27,7 @@ var ErrNicknameTooLong = errors.Errorf("nicknames must be %d "+ func IsValid(nick string) error { if nick == "" { jww.INFO.Printf( - "empty nickname passed, treating like no nickname") + "Empty nickname passed; treating it as if no nickname was set.") return nil } diff --git a/notifications/data.go b/notifications/data.go index 9b0aad2f3dfae84d79d74df566fa4eeaa927cb4c..50899f7b0b4cd1c2c515625cef3a2613d6905371 100644 --- a/notifications/data.go +++ b/notifications/data.go @@ -11,6 +11,7 @@ import ( "bytes" "encoding/base64" "encoding/csv" + "strconv" "strings" "github.com/pkg/errors" @@ -24,6 +25,16 @@ type Data struct { MessageHash []byte } +func (d *Data) String() string { + fields := []string{ + strconv.FormatInt(d.EphemeralID, 10), + strconv.FormatUint(d.RoundID, 10), + base64.StdEncoding.EncodeToString(d.IdentityFP), + base64.StdEncoding.EncodeToString(d.MessageHash), + } + return "{" + strings.Join(fields, " ") + "}" +} + // BuildNotificationCSV converts the [Data] list into a CSV of the specified max // size and return it along with the included [Data] entries. Any [Data] entries // over that size are excluded. @@ -35,7 +46,7 @@ func BuildNotificationCSV(ndList []*Data, maxSize int) ([]byte, []*Data) { var buf bytes.Buffer var numWritten int - for _, nd := range ndList { + for i, nd := range ndList { var line bytes.Buffer w := csv.NewWriter(&line) output := []string{ @@ -43,7 +54,8 @@ func BuildNotificationCSV(ndList []*Data, maxSize int) ([]byte, []*Data) { base64.StdEncoding.EncodeToString(nd.IdentityFP)} if err := w.Write(output); err != nil { - jww.FATAL.Printf("Failed to write notificationsCSV line: %+v", err) + jww.FATAL.Printf("Failed to write record %d of %d to "+ + "notifications CSV line buffer: %+v", i, len(ndList), err) } w.Flush() @@ -52,7 +64,8 @@ func BuildNotificationCSV(ndList []*Data, maxSize int) ([]byte, []*Data) { } if _, err := buf.Write(line.Bytes()); err != nil { - jww.FATAL.Printf("Failed to write to notificationsCSV: %+v", err) + jww.FATAL.Printf("Failed to write record %d of %d to "+ + "notifications CSV: %+v", i, len(ndList), err) } numWritten++ @@ -66,21 +79,25 @@ func DecodeNotificationsCSV(data string) ([]*Data, error) { r := csv.NewReader(strings.NewReader(data)) records, err := r.ReadAll() if err != nil { - return nil, errors.WithMessage(err, "Failed to decode notifications CSV") + return nil, errors.Wrapf(err, "Failed to read notifications CSV records.") } list := make([]*Data, len(records)) for i, tuple := range records { messageHash, err := base64.StdEncoding.DecodeString(tuple[0]) if err != nil { - return nil, errors.WithMessage(err, "Failed decode an element") + return nil, errors.Wrapf(err, + "Failed to decode MessageHash for record %d of %d", + i, len(records)) } + identityFP, err := base64.StdEncoding.DecodeString(tuple[1]) if err != nil { - return nil, errors.WithMessage(err, "Failed decode an element") + return nil, errors.Wrapf(err, + "Failed to decode IdentityFP for record %d of %d", + i, len(records)) } list[i] = &Data{ - EphemeralID: 0, IdentityFP: identityFP, MessageHash: messageHash, } diff --git a/notifications/data_test.go b/notifications/data_test.go index 44938899342269ffb53c64ee80a25654ce07f9e6..d4b4da519b332aca50159a94cb05d3e6c3a1ccb7 100644 --- a/notifications/data_test.go +++ b/notifications/data_test.go @@ -141,7 +141,7 @@ GsvgcJsHWAg/YdN1vAK0HfT5GSnhj9qeb4LlTnSOgec=,nku9b+NM3LqEPujWPoxP/hzr6lRtj6wT3Q= func TestDecodeNotificationsCSV_InvalidMessageHashError(t *testing.T) { invalidCSV := `U4x/lrFkvxuXu59LtHLonnZND6SugndnVI=,39ebTXZCm2F6DJ+fDTulWwzA1hRMiIU1hA== ` - expectedErr := "Failed decode an element" + expectedErr := "Failed to decode MessageHash for record 0 of 1" _, err := DecodeNotificationsCSV(invalidCSV) if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Errorf("Unexpected error for invalid MessageHash."+ @@ -154,7 +154,7 @@ func TestDecodeNotificationsCSV_InvalidMessageHashError(t *testing.T) { func TestDecodeNotificationsCSV_InvalididentityFPError(t *testing.T) { invalidCSV := `U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVI=,39ebTXZCm2F6DJ1hRMiIU1hA== ` - expectedErr := "Failed decode an element" + expectedErr := "Failed to decode IdentityFP for record 0 of 1" _, err := DecodeNotificationsCSV(invalidCSV) if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Errorf("Unexpected error for invalid identityFP."+ @@ -166,7 +166,7 @@ func TestDecodeNotificationsCSV_InvalididentityFPError(t *testing.T) { // an invalid identityFP. func TestDecodeNotificationsCSV_NoEofError(t *testing.T) { invalidCSV := `U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVI=,39ebTXZCm2F6DJ+fDTulWwzA1hRMiIU1hA==,"` - expectedErr := "Failed to decode notifications CSV" + expectedErr := "Failed to read notifications CSV records." _, err := DecodeNotificationsCSV(invalidCSV) if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Errorf("Unexpected error for invalid identityFP."+ diff --git a/states/state.go b/states/state.go index 95cd44c7ad00c378861bdc9cd2c897d93b89745e..a53e5bf3a67b3366292acf1ac6e76e541299bf9c 100644 --- a/states/state.go +++ b/states/state.go @@ -7,9 +7,7 @@ package states -import ( - "fmt" -) +import "strconv" // This holds the enum for the states of a round. It is in primitives so // other repos such as registration/permissioning, gateway, and client can @@ -49,6 +47,6 @@ func (r Round) String() string { case FAILED: return "FAILED" default: - return fmt.Sprintf("UNKNOWN STATE: %d", r) + return "UNKNOWN STATE: " + strconv.FormatUint(uint64(r), 10) } }