diff --git a/dcrec/secp256k1/field.go b/dcrec/secp256k1/field.go index d2740b58..2f28fe36 100644 --- a/dcrec/secp256k1/field.go +++ b/dcrec/secp256k1/field.go @@ -1,6 +1,6 @@ // Copyright (c) 2013-2014 The btcsuite developers -// Copyright (c) 2015-2017 The Decred developers -// Copyright (c) 2013-2014 Dave Collins +// Copyright (c) 2015-2020 The Decred developers +// Copyright (c) 2013-2020 Dave Collins // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/dcrec/secp256k1/field_test.go b/dcrec/secp256k1/field_test.go index 5b482664..28ca0bbc 100644 --- a/dcrec/secp256k1/field_test.go +++ b/dcrec/secp256k1/field_test.go @@ -1,6 +1,6 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2017 The Decred developers -// Copyright (c) 2013-2017 Dave Collins +// Copyright (c) 2015-2020 The Decred developers +// Copyright (c) 2013-2020 Dave Collins // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -15,8 +15,8 @@ import ( "time" ) -// randFieldVal returns a fieldVal created from a random value generated by the -// passed rng. +// randFieldVal returns a field value created from a random value generated by +// the passed rng. func randFieldVal(t *testing.T, rng *rand.Rand) *fieldVal { t.Helper() @@ -31,8 +31,8 @@ func randFieldVal(t *testing.T, rng *rand.Rand) *fieldVal { return &fv } -// randIntAndFieldVal returns a big integer and fieldVal both created from the -// same random value generated by the passed rng. +// randIntAndFieldVal returns a big integer and a field value both created from +// the same random value generated by the passed rng. func randIntAndFieldVal(t *testing.T, rng *rand.Rand) (*big.Int, *fieldVal) { t.Helper() @@ -49,68 +49,81 @@ func randIntAndFieldVal(t *testing.T, rng *rand.Rand) (*big.Int, *fieldVal) { return bigIntVal, &fv } -// TestSetInt ensures that setting a field value to various native integers -// works as expected. -func TestSetInt(t *testing.T) { +// TestFieldSetInt ensures that setting a field value to various native +// integers works as expected. +func TestFieldSetInt(t *testing.T) { tests := []struct { - in uint - raw [10]uint32 - }{ - {5, [10]uint32{5, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - // 2^26 - {67108864, [10]uint32{67108864, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - // 2^26 + 1 - {67108865, [10]uint32{67108865, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - // 2^32 - 1 - {4294967295, [10]uint32{4294967295, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - } + name string // test description + in uint // test value + expected [10]uint32 // expected raw ints + }{{ + name: "five", + in: 5, + expected: [10]uint32{5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^26", + in: 67108864, + expected: [10]uint32{67108864, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^26 + 1", + in: 67108865, + expected: [10]uint32{67108865, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^32 - 1", + in: 4294967295, + expected: [10]uint32{4294967295, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { + for _, test := range tests { f := new(fieldVal).SetInt(test.in) - if !reflect.DeepEqual(f.n, test.raw) { - t.Errorf("fieldVal.Set #%d wrong result\ngot: %v\n"+ - "want: %v", i, f.n, test.raw) + if !reflect.DeepEqual(f.n, test.expected) { + t.Errorf("%s: wrong result\ngot: %v\nwant: %v", test.name, f.n, + test.expected) continue } } } -// TestZero ensures that zeroing a field value works as expected. -func TestZero(t *testing.T) { - f := new(fieldVal).SetInt(2) +// TestFieldZero ensures that zeroing a field value works as expected. +func TestFieldZero(t *testing.T) { + var f fieldVal + f.SetHex("a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5") f.Zero() for idx, rawInt := range f.n { if rawInt != 0 { - t.Errorf("internal field integer at index #%d is not "+ - "zero - got %d", idx, rawInt) + t.Errorf("internal integer at index #%d is not zero - got %d", idx, + rawInt) } } } -// TestIsZero ensures that checking if a field is zero works as expected. -func TestIsZero(t *testing.T) { +// TestFieldIsZero ensures that checking if a field is zero works as +// expected. +func TestFieldIsZero(t *testing.T) { f := new(fieldVal) if !f.IsZero() { - t.Errorf("new field value is not zero - got %v (rawints %x)", f, - f.n) + t.Errorf("new field value is not zero - got %v (rawints %x)", f, f.n) } f.SetInt(1) if f.IsZero() { - t.Errorf("field claims it's zero when it's not - got %v "+ - "(raw rawints %x)", f, f.n) + t.Errorf("claims zero for nonzero field - got %v (rawints %x)", f, f.n) } f.Zero() if !f.IsZero() { - t.Errorf("field claims it's not zero when it is - got %v "+ - "(raw rawints %x)", f, f.n) + t.Errorf("claims nonzero for zero field - got %v (rawints %x)", f, f.n) + } + + f.SetInt(1) + f.Zero() + if !f.IsZero() { + t.Errorf("claims zero for nonzero field - got %v (rawints %x)", f, f.n) } } -// TestIsOne ensures that checking if a field is one works as expected. -func TestIsOne(t *testing.T) { +// TestFieldIsOne ensures that checking if a field is one works as expected. +func TestFieldIsOne(t *testing.T) { tests := []struct { name string // test description in string // hex encoded test value @@ -200,706 +213,852 @@ func TestIsOne(t *testing.T) { } result := f.IsOne() if result != test.expected { - t.Errorf("%s: wrong result\ngot: %v\nwant: %v", test.name, + t.Errorf("%s: wrong result\ngot: %v\nwant: %v", test.name, result, + test.expected) + continue + } + } +} + +// TestFieldStringer ensures the stringer returns the appropriate hex string. +func TestFieldStringer(t *testing.T) { + tests := []struct { + name string //test description + in string // hex encoded test value + expected string // expected result + }{{ + name: "zero", + in: "0", + expected: "0000000000000000000000000000000000000000000000000000000000000000", + }, { + name: "one", + in: "1", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + }, { + name: "ten", + in: "a", + expected: "000000000000000000000000000000000000000000000000000000000000000a", + }, { + name: "eleven", + in: "b", + expected: "000000000000000000000000000000000000000000000000000000000000000b", + }, { + name: "twelve", + in: "c", + expected: "000000000000000000000000000000000000000000000000000000000000000c", + }, { + name: "thirteen", + in: "d", + expected: "000000000000000000000000000000000000000000000000000000000000000d", + }, { + name: "fourteen", + in: "e", + expected: "000000000000000000000000000000000000000000000000000000000000000e", + }, { + name: "fifteen", + in: "f", + expected: "000000000000000000000000000000000000000000000000000000000000000f", + }, { + name: "240", + in: "f0", + expected: "00000000000000000000000000000000000000000000000000000000000000f0", + }, { + name: "2^26 - 1", + in: "3ffffff", + expected: "0000000000000000000000000000000000000000000000000000000003ffffff", + }, { + name: "2^32 - 1", + in: "ffffffff", + expected: "00000000000000000000000000000000000000000000000000000000ffffffff", + }, { + name: "2^64 - 1", + in: "ffffffffffffffff", + expected: "000000000000000000000000000000000000000000000000ffffffffffffffff", + }, { + name: "2^96 - 1", + in: "ffffffffffffffffffffffff", + expected: "0000000000000000000000000000000000000000ffffffffffffffffffffffff", + }, { + name: "2^128 - 1", + in: "ffffffffffffffffffffffffffffffff", + expected: "00000000000000000000000000000000ffffffffffffffffffffffffffffffff", + }, { + name: "2^160 - 1", + in: "ffffffffffffffffffffffffffffffffffffffff", + expected: "000000000000000000000000ffffffffffffffffffffffffffffffffffffffff", + }, { + name: "2^192 - 1", + in: "ffffffffffffffffffffffffffffffffffffffffffffffff", + expected: "0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff", + }, { + name: "2^224 - 1", + in: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + expected: "00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + }, { + name: "2^256-4294968273 (the secp256k1 prime, so should result in 0)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: "0000000000000000000000000000000000000000000000000000000000000000", + }, { + name: "2^256-4294968274 (the secp256k1 prime+1, so should result in 1)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + }, { + name: "invalid hex g", + in: "g", + expected: "0000000000000000000000000000000000000000000000000000000000000000", + }, { + name: "invalid hex 1h", + in: "1h", + expected: "0000000000000000000000000000000000000000000000000000000000000000", + }, { + name: "invalid hex i1", + in: "i1", + expected: "0000000000000000000000000000000000000000000000000000000000000000", + }} + + for _, test := range tests { + f := new(fieldVal).SetHex(test.in) + result := f.String() + if result != test.expected { + t.Errorf("%s: wrong result\ngot: %v\nwant: %v", test.name, result, + test.expected) + continue + } + } +} + +// TestFieldNormalize ensures that normalizing the internal field words works as +// expected. +func TestFieldNormalize(t *testing.T) { + tests := []struct { + name string // test description + raw [10]uint32 // Intentionally denormalized value + normalized [10]uint32 // Normalized form of the raw value + }{{ + name: "5", + raw: [10]uint32{0x00000005, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x00000005, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^26", + raw: [10]uint32{0x04000000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x00000000, 0x1, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^26 + 1", + raw: [10]uint32{0x04000001, 0x0, 0, 0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x00000001, 0x1, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^32 - 1", + raw: [10]uint32{0xffffffff, 0x00, 0, 0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x03ffffff, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^32", + raw: [10]uint32{0x04000000, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x00000000, 0x40, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^32 + 1", + raw: [10]uint32{0x04000001, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x00000001, 0x40, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^64 - 1", + raw: [10]uint32{0xffffffff, 0xffffffc0, 0xfc0, 0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x03ffffff, 0x03ffffff, 0xfff, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^64", + raw: [10]uint32{0x04000000, 0x03ffffff, 0x0fff, 0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x00000000, 0x00000000, 0x1000, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^64 + 1", + raw: [10]uint32{0x04000001, 0x03ffffff, 0x0fff, 0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x00000001, 0x00000000, 0x1000, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^96 - 1", + raw: [10]uint32{0xffffffff, 0xffffffc0, 0xffffffc0, 0x3ffc0, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x03ffffff, 0x03ffffff, 0x03ffffff, 0x3ffff, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^96", + raw: [10]uint32{0x04000000, 0x03ffffff, 0x03ffffff, 0x3ffff, 0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x00000000, 0x00000000, 0x00000000, 0x40000, 0, 0, 0, 0, 0, 0}, + }, { + name: "2^128 - 1", + raw: [10]uint32{0xffffffff, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffc0, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0xffffff, 0, 0, 0, 0, 0}, + }, { + name: "2^128", + raw: [10]uint32{0x04000000, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x0ffffff, 0, 0, 0, 0, 0}, + normalized: [10]uint32{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1000000, 0, 0, 0, 0, 0}, + }, { + name: "2^256 - 4294968273 (secp256k1 prime)", + raw: [10]uint32{0xfffffc2f, 0xffffff80, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0}, + normalized: [10]uint32{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000}, + }, { + // Value larger than P where both first and second words are larger than + // P's first and second words + name: "Value > P with 1st and 2nd words > P's 1st and 2nd words", + raw: [10]uint32{0xfffffc30, 0xffffff86, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0}, + normalized: [10]uint32{0x00000001, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000}, + }, { + // Value larger than P where only the second word is larger than P's + // second word. + name: "Value > P with 2nd word > P's 2nd word", + raw: [10]uint32{0xfffffc2a, 0xffffff87, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0}, + normalized: [10]uint32{0x03fffffb, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000}, + }, { + name: "2^256 - 1", + raw: [10]uint32{0xffffffff, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0}, + normalized: [10]uint32{0x000003d0, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000}, + }, { + // Prime with field representation such that the initial reduction does + // not result in a carry to bit 256. + // + // 2^256 - 4294968273 (secp256k1 prime) + name: "2^256 - 4294968273 (secp256k1 prime)", + raw: [10]uint32{0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff}, + normalized: [10]uint32{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + }, { + // Value larger than P that reduces to a value which is still larger + // than P when it has a magnitude of 1 due to its first word and does + // not result in a carry to bit 256. + // + // 2^256 - 4294968272 (secp256k1 prime + 1) + name: "2^256 - 4294968272 (secp256k1 prime + 1)", + raw: [10]uint32{0x03fffc30, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff}, + normalized: [10]uint32{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + }, { + // Value larger than P that reduces to a value which is still larger + // than P when it has a magnitude of 1 due to its second word and does + // not result in a carry to bit 256. + // + // 2^256 - 4227859409 (secp256k1 prime + 0x4000000) + name: "2^256 - 4227859409 (secp256k1 prime + 0x4000000)", + raw: [10]uint32{0x03fffc2f, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff}, + normalized: [10]uint32{0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + }, { + // Value larger than P that reduces to a value which is still larger + // than P when it has a magnitude of 1 due to a carry to bit 256, but + // would not be without the carry. These values come from the fact that + // P is 2^256 - 4294968273 and 977 is the low order word in the internal + // field representation. + // + // 2^256 * 5 - ((4294968273 - (977+1)) * 4) + name: "2^256 * 5 - ((4294968273 - (977+1)) * 4)", + raw: [10]uint32{0x03ffffff, 0x03fffeff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x0013fffff}, + normalized: [10]uint32{0x00001314, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000000}, + }, { + // Value larger than P that reduces to a value which is still larger + // than P when it has a magnitude of 1 due to both a carry to bit 256 + // and the first word. + name: "Value > P with redux > P at mag 1 due to 1st word and carry to bit 256", + raw: [10]uint32{0x03fffc30, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x07ffffff, 0x003fffff}, + normalized: [10]uint32{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001}, + }, { + // Value larger than P that reduces to a value which is still larger + // than P when it has a magnitude of 1 due to both a carry to bit 256 + // and the second word. + name: "Value > P with redux > P at mag 1 due to 2nd word and carry to bit 256", + raw: [10]uint32{0x03fffc2f, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x3ffffff, 0x07ffffff, 0x003fffff}, + normalized: [10]uint32{0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000, 0x00000000, 0x00000001}, + }, { + // Value larger than P that reduces to a value which is still larger + // than P when it has a magnitude of 1 due to a carry to bit 256 and the + // first and second words. + name: "Value > P with redux > P at mag 1 due to 1st and 2nd words and carry to bit 256", + raw: [10]uint32{0x03fffc30, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x07ffffff, 0x003fffff}, + normalized: [10]uint32{0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001}, + }} + + for _, test := range tests { + f := new(fieldVal) + f.n = test.raw + f.Normalize() + if !reflect.DeepEqual(f.n, test.normalized) { + t.Errorf("%s: wrong normalized result\ngot: %x\nwant: %x", + test.name, f.n, test.normalized) + continue + } + } +} + +// TestFieldIsOdd ensures that checking if a field value IsOdd works as +// expected. +func TestFieldIsOdd(t *testing.T) { + tests := []struct { + name string // test description + in string // hex encoded value + expected bool // expected oddness + }{{ + name: "zero", + in: "0", + expected: false, + }, { + name: "one", + in: "1", + expected: true, + }, { + name: "two", + in: "2", + expected: false, + }, { + name: "2^32 - 1", + in: "ffffffff", + expected: true, + }, { + name: "2^64 - 2", + in: "fffffffffffffffe", + expected: false, + }, { + name: "secp256k1 prime (not normalized so should be incorrect result)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: true, + }, { + name: "secp256k1 prime + 1 (not normalized so should be incorrect result)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + expected: false, + }} + + for _, test := range tests { + result := new(fieldVal).SetHex(test.in).IsOdd() + if result != test.expected { + t.Errorf("%s: wrong result -- got: %v, want: %v", test.name, result, test.expected) continue } } } -// TestStringer ensures the stringer returns the appropriate hex string. -func TestStringer(t *testing.T) { - tests := []struct { - in string - expected string - }{ - {"0", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"1", "0000000000000000000000000000000000000000000000000000000000000001"}, - {"a", "000000000000000000000000000000000000000000000000000000000000000a"}, - {"b", "000000000000000000000000000000000000000000000000000000000000000b"}, - {"c", "000000000000000000000000000000000000000000000000000000000000000c"}, - {"d", "000000000000000000000000000000000000000000000000000000000000000d"}, - {"e", "000000000000000000000000000000000000000000000000000000000000000e"}, - {"f", "000000000000000000000000000000000000000000000000000000000000000f"}, - {"f0", "00000000000000000000000000000000000000000000000000000000000000f0"}, - // 2^26-1 - { - "3ffffff", - "0000000000000000000000000000000000000000000000000000000003ffffff", - }, - // 2^32-1 - { - "ffffffff", - "00000000000000000000000000000000000000000000000000000000ffffffff", - }, - // 2^64-1 - { - "ffffffffffffffff", - "000000000000000000000000000000000000000000000000ffffffffffffffff", - }, - // 2^96-1 - { - "ffffffffffffffffffffffff", - "0000000000000000000000000000000000000000ffffffffffffffffffffffff", - }, - // 2^128-1 - { - "ffffffffffffffffffffffffffffffff", - "00000000000000000000000000000000ffffffffffffffffffffffffffffffff", - }, - // 2^160-1 - { - "ffffffffffffffffffffffffffffffffffffffff", - "000000000000000000000000ffffffffffffffffffffffffffffffffffffffff", - }, - // 2^192-1 - { - "ffffffffffffffffffffffffffffffffffffffffffffffff", - "0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff", - }, - // 2^224-1 - { - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - }, - // 2^256-4294968273 (the secp256k1 prime, so should result in 0) - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "0000000000000000000000000000000000000000000000000000000000000000", - }, - // 2^256-4294968274 (the secp256k1 prime+1, so should result in 1) - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "0000000000000000000000000000000000000000000000000000000000000001", - }, - - // Invalid hex - {"g", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"1h", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"i1", "0000000000000000000000000000000000000000000000000000000000000000"}, - } - - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in) - result := f.String() - if result != test.expected { - t.Errorf("fieldVal.String #%d wrong result\ngot: %v\n"+ - "want: %v", i, result, test.expected) - continue - } - } -} - -// TestNormalize ensures that normalizing the internal field words works as -// expected. -func TestNormalize(t *testing.T) { - tests := []struct { - raw [10]uint32 // Intentionally denormalized value - normalized [10]uint32 // Normalized form of the raw value - }{ - { - [10]uint32{0x00000005, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x00000005, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - }, - // 2^26 - { - [10]uint32{0x04000000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x00000000, 0x1, 0, 0, 0, 0, 0, 0, 0, 0}, - }, - // 2^26 + 1 - { - [10]uint32{0x04000001, 0x0, 0, 0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x00000001, 0x1, 0, 0, 0, 0, 0, 0, 0, 0}, - }, - // 2^32 - 1 - { - [10]uint32{0xffffffff, 0x00, 0, 0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x03ffffff, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0}, - }, - // 2^32 - { - [10]uint32{0x04000000, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x00000000, 0x40, 0, 0, 0, 0, 0, 0, 0, 0}, - }, - // 2^32 + 1 - { - [10]uint32{0x04000001, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x00000001, 0x40, 0, 0, 0, 0, 0, 0, 0, 0}, - }, - // 2^64 - 1 - { - [10]uint32{0xffffffff, 0xffffffc0, 0xfc0, 0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x03ffffff, 0x03ffffff, 0xfff, 0, 0, 0, 0, 0, 0, 0}, - }, - // 2^64 - { - [10]uint32{0x04000000, 0x03ffffff, 0x0fff, 0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x00000000, 0x00000000, 0x1000, 0, 0, 0, 0, 0, 0, 0}, - }, - // 2^64 + 1 - { - [10]uint32{0x04000001, 0x03ffffff, 0x0fff, 0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x00000001, 0x00000000, 0x1000, 0, 0, 0, 0, 0, 0, 0}, - }, - // 2^96 - 1 - { - [10]uint32{0xffffffff, 0xffffffc0, 0xffffffc0, 0x3ffc0, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x03ffffff, 0x03ffffff, 0x03ffffff, 0x3ffff, 0, 0, 0, 0, 0, 0}, - }, - // 2^96 - { - [10]uint32{0x04000000, 0x03ffffff, 0x03ffffff, 0x3ffff, 0, 0, 0, 0, 0, 0}, - [10]uint32{0x00000000, 0x00000000, 0x00000000, 0x40000, 0, 0, 0, 0, 0, 0}, - }, - // 2^128 - 1 - { - [10]uint32{0xffffffff, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffc0, 0, 0, 0, 0, 0}, - [10]uint32{0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0xffffff, 0, 0, 0, 0, 0}, - }, - // 2^128 - { - [10]uint32{0x04000000, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x0ffffff, 0, 0, 0, 0, 0}, - [10]uint32{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1000000, 0, 0, 0, 0, 0}, - }, - // 2^256 - 4294968273 (secp256k1 prime) - { - [10]uint32{0xfffffc2f, 0xffffff80, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0}, - [10]uint32{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000}, - }, - // Prime larger than P where both first and second words are larger - // than P's first and second words - { - [10]uint32{0xfffffc30, 0xffffff86, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0}, - [10]uint32{0x00000001, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000}, - }, - // Prime larger than P where only the second word is larger - // than P's second words. - { - [10]uint32{0xfffffc2a, 0xffffff87, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0}, - [10]uint32{0x03fffffb, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000}, - }, - // 2^256 - 1 - { - [10]uint32{0xffffffff, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0}, - [10]uint32{0x000003d0, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000}, - }, - // Prime with field representation such that the initial - // reduction does not result in a carry to bit 256. - // - // 2^256 - 4294968273 (secp256k1 prime) - { - [10]uint32{0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff}, - [10]uint32{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - }, - // Prime larger than P that reduces to a value which is still - // larger than P when it has a magnitude of 1 due to its first - // word and does not result in a carry to bit 256. - // - // 2^256 - 4294968272 (secp256k1 prime + 1) - { - [10]uint32{0x03fffc30, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff}, - [10]uint32{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - }, - // Prime larger than P that reduces to a value which is still - // larger than P when it has a magnitude of 1 due to its second - // word and does not result in a carry to bit 256. - // - // 2^256 - 4227859409 (secp256k1 prime + 0x4000000) - { - [10]uint32{0x03fffc2f, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff}, - [10]uint32{0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - }, - // Prime larger than P that reduces to a value which is still - // larger than P when it has a magnitude of 1 due to a carry to - // bit 256, but would not be without the carry. These values - // come from the fact that P is 2^256 - 4294968273 and 977 is - // the low order word in the internal field representation. - // - // 2^256 * 5 - ((4294968273 - (977+1)) * 4) - { - [10]uint32{0x03ffffff, 0x03fffeff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x0013fffff}, - [10]uint32{0x00001314, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000000}, - }, - // Prime larger than P that reduces to a value which is still - // larger than P when it has a magnitude of 1 due to both a - // carry to bit 256 and the first word. - { - [10]uint32{0x03fffc30, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x07ffffff, 0x003fffff}, - [10]uint32{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001}, - }, - // Prime larger than P that reduces to a value which is still - // larger than P when it has a magnitude of 1 due to both a - // carry to bit 256 and the second word. - // - { - [10]uint32{0x03fffc2f, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x3ffffff, 0x07ffffff, 0x003fffff}, - [10]uint32{0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000, 0x00000000, 0x00000001}, - }, - // Prime larger than P that reduces to a value which is still - // larger than P when it has a magnitude of 1 due to a carry to - // bit 256 and the first and second words. - // - { - [10]uint32{0x03fffc30, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x07ffffff, 0x003fffff}, - [10]uint32{0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001}, - }, - } - - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal) - f.n = test.raw - f.Normalize() - if !reflect.DeepEqual(f.n, test.normalized) { - t.Errorf("fieldVal.Set #%d wrong normalized result\n"+ - "got: %x\nwant: %x", i, f.n, test.normalized) - continue - } - } -} - -// TestIsOdd ensures that checking if a field value IsOdd works as expected. -func TestIsOdd(t *testing.T) { - tests := []struct { - in string // hex encoded value - expected bool // expected oddness - }{ - {"0", false}, - {"1", true}, - {"2", false}, - // 2^32 - 1 - {"ffffffff", true}, - // 2^64 - 2 - {"fffffffffffffffe", false}, - // secp256k1 prime - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", true}, - } - - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in) - result := f.IsOdd() - if result != test.expected { - t.Errorf("fieldVal.IsOdd #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, test.expected) - continue - } - } -} - -// TestEquals ensures that checking two field values for equality via Equals -// works as expected. -func TestEquals(t *testing.T) { +// TestFieldEquals ensures that checking two field values for equality via +// Equals works as expected. +func TestFieldEquals(t *testing.T) { tests := []struct { + name string // test description in1 string // hex encoded value in2 string // hex encoded value expected bool // expected equality - }{ - {"0", "0", true}, - {"0", "1", false}, - {"1", "0", false}, - // 2^32 - 1 == 2^32 - 1? - {"ffffffff", "ffffffff", true}, - // 2^64 - 1 == 2^64 - 2? - {"ffffffffffffffff", "fffffffffffffffe", false}, - // 0 == prime (mod prime)? - {"0", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", true}, - // 1 == prime+1 (mod prime)? - {"1", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", true}, - } + }{{ + name: "0 == 0?", + in1: "0", + in2: "0", + expected: true, + }, { + name: "0 == 1?", + in1: "0", + in2: "1", + expected: false, + }, { + name: "1 == 0?", + in1: "1", + in2: "0", + expected: false, + }, { + name: "2^32 - 1 == 2^32 - 1?", + in1: "ffffffff", + in2: "ffffffff", + expected: true, + }, { + name: "2^64 - 1 == 2^64 - 2?", + in1: "ffffffffffffffff", + in2: "fffffffffffffffe", + expected: false, + }, { + name: "0 == prime (mod prime)?", + in1: "0", + in2: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: true, + }, { + name: "1 == prime + 1 (mod prime)?", + in1: "1", + in2: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + expected: true, + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { + for _, test := range tests { f := new(fieldVal).SetHex(test.in1).Normalize() f2 := new(fieldVal).SetHex(test.in2).Normalize() result := f.Equals(f2) if result != test.expected { - t.Errorf("fieldVal.Equals #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, test.expected) + t.Errorf("%s: wrong result -- got: %v, want: %v", test.name, result, + test.expected) continue } } } -// TestNegate ensures that negating field values via Negate works as expected. -func TestNegate(t *testing.T) { +// TestFieldNegate ensures that negating field values via Negate works as +// expected. +func TestFieldNegate(t *testing.T) { tests := []struct { - in string // hex encoded value - expected string // expected hex encoded value - }{ - // secp256k1 prime (aka 0) - {"0", "0"}, - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "0"}, - {"0", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"}, - // secp256k1 prime-1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1"}, - {"1", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e"}, - // secp256k1 prime-2 - {"2", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d"}, - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", "2"}, - // Random sampling - { - "b3d9aac9c5e43910b4385b53c7e78c21d4cd5f8e683c633aed04c233efc2e120", - "4c2655363a1bc6ef4bc7a4ac381873de2b32a07197c39cc512fb3dcb103d1b0f", - }, - { - "f8a85984fee5a12a7c8dd08830d83423c937d77c379e4a958e447a25f407733f", - "757a67b011a5ed583722f77cf27cbdc36c82883c861b56a71bb85d90bf888f0", - }, - { - "45ee6142a7fda884211e93352ed6cb2807800e419533be723a9548823ece8312", - "ba119ebd5802577bdee16ccad12934d7f87ff1be6acc418dc56ab77cc131791d", - }, - { - "53c2a668f07e411a2e473e1c3b6dcb495dec1227af27673761d44afe5b43d22b", - "ac3d59970f81bee5d1b8c1e3c49234b6a213edd850d898c89e2bb500a4bc2a04", - }, - } + name string // test description + in string // hex encoded test value + expected string // hex encoded expected result + }{{ + name: "zero", + in: "0", + expected: "0", + }, { + name: "secp256k1 prime (direct val in with 0 out)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: "0", + }, { + name: "secp256k1 prime (0 in with direct val out)", + in: "0", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + }, { + name: "1 -> secp256k1 prime - 1", + in: "1", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + }, { + name: "secp256k1 prime - 1 -> 1", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + expected: "1", + }, { + name: "2 -> secp256k1 prime - 2", + in: "2", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + }, { + name: "secp256k1 prime - 2 -> 2", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + expected: "2", + }, { + name: "random sampling #1", + in: "b3d9aac9c5e43910b4385b53c7e78c21d4cd5f8e683c633aed04c233efc2e120", + expected: "4c2655363a1bc6ef4bc7a4ac381873de2b32a07197c39cc512fb3dcb103d1b0f", + }, { + name: "random sampling #2", + in: "f8a85984fee5a12a7c8dd08830d83423c937d77c379e4a958e447a25f407733f", + expected: "757a67b011a5ed583722f77cf27cbdc36c82883c861b56a71bb85d90bf888f0", + }, { + name: "random sampling #3", + in: "45ee6142a7fda884211e93352ed6cb2807800e419533be723a9548823ece8312", + expected: "ba119ebd5802577bdee16ccad12934d7f87ff1be6acc418dc56ab77cc131791d", + }, { + name: "random sampling #4", + in: "53c2a668f07e411a2e473e1c3b6dcb495dec1227af27673761d44afe5b43d22b", + expected: "ac3d59970f81bee5d1b8c1e3c49234b6a213edd850d898c89e2bb500a4bc2a04", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { + for _, test := range tests { f := new(fieldVal).SetHex(test.in).Normalize() expected := new(fieldVal).SetHex(test.expected).Normalize() - result := f.Negate(1).Normalize() + + // Ensure negating another value produces the expected result. + result := new(fieldVal).NegateVal(f, 1).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Negate #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: unexpected result -- got: %v, want: %v", test.name, + result, expected) + continue + } + + // Ensure self negating also produces the expected result. + result2 := f.Negate(1).Normalize() + if !result2.Equals(expected) { + t.Errorf("%s: unexpected result -- got: %v, want: %v", test.name, + result2, expected) continue } } } -// TestAddInt ensures that adding an integer to field values via AddInt works as -// expected. -func TestAddInt(t *testing.T) { +// TestFieldAddInt ensures that adding an integer to field values via AddInt +// works as expected. +func TestFieldAddInt(t *testing.T) { tests := []struct { + name string // test description in1 string // hex encoded value in2 uint // unsigned integer to add to the value above expected string // expected hex encoded value - }{ - {"0", 1, "1"}, - {"1", 0, "1"}, - {"1", 1, "2"}, - // secp256k1 prime-1 + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", 1, "0"}, - // secp256k1 prime + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 1, "1"}, - // Random samples. - { - "ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d6c1", - 0x10f, - "ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d7d0", - }, - { - "44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41deea9cecf", - 0x2cf11d41, - "44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41e1b9aec10", - }, - { - "88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f7105122c9c", - 0x4829aa2d, - "88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f714d3bd6c9", - }, - { - "8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee09a015e2a6", - 0xa21265a5, - "8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee0a4228484b", - }, - } + }{{ + name: "zero + one", + in1: "0", + in2: 1, + expected: "1", + }, { + name: "one + zero", + in1: "1", + in2: 0, + expected: "1", + }, { + name: "one + one", + in1: "1", + in2: 1, + expected: "2", + }, { + name: "secp256k1 prime-1 + 1", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: 1, + expected: "0", + }, { + name: "secp256k1 prime + 1", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + in2: 1, + expected: "1", + }, { + name: "random sampling #1", + in1: "ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d6c1", + in2: 0x10f, + expected: "ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d7d0", + }, { + name: "random sampling #2", + in1: "44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41deea9cecf", + in2: 0x2cf11d41, + expected: "44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41e1b9aec10", + }, { + name: "random sampling #3", + in1: "88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f7105122c9c", + in2: 0x4829aa2d, + expected: "88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f714d3bd6c9", + }, { + name: "random sampling #4", + in1: "8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee09a015e2a6", + in2: 0xa21265a5, + expected: "8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee0a4228484b", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { + for _, test := range tests { f := new(fieldVal).SetHex(test.in1).Normalize() expected := new(fieldVal).SetHex(test.expected).Normalize() result := f.AddInt(test.in2).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.AddInt #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: wrong result -- got: %v -- want: %v", test.name, + result, expected) continue } } } -// TestAdd ensures that adding two field values together via Add works as -// expected. -func TestAdd(t *testing.T) { +// TestFieldAdd ensures that adding two field values together via Add and Add2 +// works as expected. +func TestFieldAdd(t *testing.T) { tests := []struct { + name string // test description in1 string // first hex encoded value in2 string // second hex encoded value to add expected string // expected hex encoded value - }{ - {"0", "1", "1"}, - {"1", "0", "1"}, - {"1", "1", "2"}, - // secp256k1 prime-1 + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1", "0"}, - // secp256k1 prime + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "1", "1"}, - // Random samples. - { - "2b2012f975404e5065b4292fb8bed0a5d315eacf24c74d8b27e73bcc5430edcc", - "2c3cefa4e4753e8aeec6ac4c12d99da4d78accefda3b7885d4c6bab46c86db92", - "575d029e59b58cdb547ad57bcb986e4aaaa0b7beff02c610fcadf680c0b7c95e", - }, - { - "8131e8722fe59bb189692b96c9f38de92885730f1dd39ab025daffb94c97f79c", - "ff5454b765f0aab5f0977dcc629becc84cabeb9def48e79c6aadb2622c490fa9", - "80863d2995d646677a00a9632c8f7ab175315ead0d1c824c9088b21c78e10b16", - }, - { - "c7c95e93d0892b2b2cdd77e80eb646ea61be7a30ac7e097e9f843af73fad5c22", - "3afe6f91a74dfc1c7f15c34907ee981656c37236d946767dd53ccad9190e437c", - "02c7ce2577d72747abf33b3116a4df00b881ec6785c47ffc74c105d158bba36f", - }, - { - "fd1c26f6a23381e5d785ba889494ec059369b888ad8431cd67d8c934b580dbe1", - "a475aa5a31dcca90ef5b53c097d9133d6b7117474b41e7877bb199590fc0489c", - "a191d150d4104c76c6e10e492c6dff42fedacfcff8c61954e38a628ec541284e", - }, - } + }{{ + name: "zero + one", + in1: "0", + in2: "1", + expected: "1", + }, { + name: "one + zero", + in1: "1", + in2: "0", + expected: "1", + }, { + name: "secp256k1 prime-1 + 1", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: "1", + expected: "0", + }, { + name: "secp256k1 prime + 1", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + in2: "1", + expected: "1", + }, { + name: "random sampling #1", + in1: "2b2012f975404e5065b4292fb8bed0a5d315eacf24c74d8b27e73bcc5430edcc", + in2: "2c3cefa4e4753e8aeec6ac4c12d99da4d78accefda3b7885d4c6bab46c86db92", + expected: "575d029e59b58cdb547ad57bcb986e4aaaa0b7beff02c610fcadf680c0b7c95e", + }, { + name: "random sampling #2", + in1: "8131e8722fe59bb189692b96c9f38de92885730f1dd39ab025daffb94c97f79c", + in2: "ff5454b765f0aab5f0977dcc629becc84cabeb9def48e79c6aadb2622c490fa9", + expected: "80863d2995d646677a00a9632c8f7ab175315ead0d1c824c9088b21c78e10b16", + }, { + name: "random sampling #3", + in1: "c7c95e93d0892b2b2cdd77e80eb646ea61be7a30ac7e097e9f843af73fad5c22", + in2: "3afe6f91a74dfc1c7f15c34907ee981656c37236d946767dd53ccad9190e437c", + expected: "2c7ce2577d72747abf33b3116a4df00b881ec6785c47ffc74c105d158bba36f", + }, { + name: "random sampling #4", + in1: "fd1c26f6a23381e5d785ba889494ec059369b888ad8431cd67d8c934b580dbe1", + in2: "a475aa5a31dcca90ef5b53c097d9133d6b7117474b41e7877bb199590fc0489c", + expected: "a191d150d4104c76c6e10e492c6dff42fedacfcff8c61954e38a628ec541284e", + }, { + name: "random sampling #5", + in1: "ad82b8d1cc136e23e9fd77fe2c7db1fe5a2ecbfcbde59ab3529758334f862d28", + in2: "4d6a4e95d6d61f4f46b528bebe152d408fd741157a28f415639347a84f6f574b", + expected: "faed0767a2e98d7330b2a0bcea92df3eea060d12380e8ec8b62a9fdb9ef58473", + }, { + name: "random sampling #6", + in1: "f3f43a2540054a86e1df98547ec1c0e157b193e5350fb4a3c3ea214b228ac5e7", + in2: "25706572592690ea3ddc951a1b48b504a4c83dc253756e1b96d56fdfb3199522", + expected: "19649f97992bdb711fbc2d6e9a0a75e5fc79d1a7888522bf5abf912bd5a45eda", + }, { + name: "random sampling #7", + in1: "6915bb94eef13ff1bb9b2633d997e13b9b1157c713363cc0e891416d6734f5b8", + in2: "11f90d6ac6fe1c4e8900b1c85fb575c251ec31b9bc34b35ada0aea1c21eded22", + expected: "7b0ec8ffb5ef5c40449bd7fc394d56fdecfd8980cf6af01bc29c2b898922e2da", + }, { + name: "random sampling #8", + in1: "48b0c9eae622eed9335b747968544eb3e75cb2dc8128388f948aa30f88cabde4", + in2: "0989882b52f85f9d524a3a3061a0e01f46d597839d2ba637320f4b9510c8d2d5", + expected: "523a5216391b4e7685a5aea9c9f52ed32e324a601e53dec6c699eea4999390b9", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in1).Normalize() + for _, test := range tests { + // Parse test hex. + f1 := new(fieldVal).SetHex(test.in1).Normalize() f2 := new(fieldVal).SetHex(test.in2).Normalize() expected := new(fieldVal).SetHex(test.expected).Normalize() - result := f.Add(f2).Normalize() + + // Ensure adding the two values with the result going to another + // variable produces the expected result. + result := new(fieldVal).Add2(f1, f2).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Add #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + result, expected) + continue + } + + // Ensure adding the value to an existing field value produces the + // expected result. + f1.Add(f2).Normalize() + if !f1.Equals(expected) { + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + f1, expected) continue } } } -// TestAdd2 ensures that adding two field values together via Add2 works as -// expected. -func TestAdd2(t *testing.T) { - tests := []struct { - in1 string // first hex encoded value - in2 string // second hex encoded value to add - expected string // expected hex encoded value - }{ - {"0", "1", "1"}, - {"1", "0", "1"}, - {"1", "1", "2"}, - // secp256k1 prime-1 + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1", "0"}, - // secp256k1 prime + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "1", "1"}, - // close but over the secp256k1 prime - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000", "f1ffff000", "1ffff3d1"}, - // Random samples. - { - "ad82b8d1cc136e23e9fd77fe2c7db1fe5a2ecbfcbde59ab3529758334f862d28", - "4d6a4e95d6d61f4f46b528bebe152d408fd741157a28f415639347a84f6f574b", - "faed0767a2e98d7330b2a0bcea92df3eea060d12380e8ec8b62a9fdb9ef58473", - }, - { - "f3f43a2540054a86e1df98547ec1c0e157b193e5350fb4a3c3ea214b228ac5e7", - "25706572592690ea3ddc951a1b48b504a4c83dc253756e1b96d56fdfb3199522", - "19649f97992bdb711fbc2d6e9a0a75e5fc79d1a7888522bf5abf912bd5a45eda", - }, - { - "6915bb94eef13ff1bb9b2633d997e13b9b1157c713363cc0e891416d6734f5b8", - "11f90d6ac6fe1c4e8900b1c85fb575c251ec31b9bc34b35ada0aea1c21eded22", - "7b0ec8ffb5ef5c40449bd7fc394d56fdecfd8980cf6af01bc29c2b898922e2da", - }, - { - "48b0c9eae622eed9335b747968544eb3e75cb2dc8128388f948aa30f88cabde4", - "0989882b52f85f9d524a3a3061a0e01f46d597839d2ba637320f4b9510c8d2d5", - "523a5216391b4e7685a5aea9c9f52ed32e324a601e53dec6c699eea4999390b9", - }, - } - - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in1).Normalize() - f2 := new(fieldVal).SetHex(test.in2).Normalize() - expected := new(fieldVal).SetHex(test.expected).Normalize() - result := f.Add2(f, f2).Normalize() - if !result.Equals(expected) { - t.Errorf("fieldVal.Add2 #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) - continue - } - } -} - -// TestMulInt ensures that adding an integer to field values via MulInt works as -// expected. -func TestMulInt(t *testing.T) { +// TestFieldMulInt ensures that multiplying an integer to field values via +// MulInt works as expected. +func TestFieldMulInt(t *testing.T) { tests := []struct { + name string // test description in1 string // hex encoded value in2 uint // unsigned integer to multiply with value above expected string // expected hex encoded value - }{ - {"0", 0, "0"}, - {"1", 0, "0"}, - {"0", 1, "0"}, - {"1", 1, "1"}, - // secp256k1 prime-1 * 2 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - 2, - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", - }, - // secp256k1 prime * 3 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 3, "0"}, - // secp256k1 prime-1 * 8 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - 8, - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27", - }, + }{{ + name: "zero * zero", + in1: "0", + in2: 0, + expected: "0", + }, { + name: "one * zero", + in1: "1", + in2: 0, + expected: "0", + }, { + name: "zero * one", + in1: "0", + in2: 1, + expected: "0", + }, { + name: "one * one", + in1: "1", + in2: 1, + expected: "1", + }, { + name: "secp256k1 prime-1 * 2", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: 2, + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + }, { + name: "secp256k1 prime * 3", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + in2: 3, + expected: "0", + }, { + name: "secp256k1 prime-1 * 8", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: 8, + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27", + }, { // Random samples for first value. The second value is limited // to 8 since that is the maximum int used in the elliptic curve // calculations. - { - "b75674dc9180d306c692163ac5e089f7cef166af99645c0c23568ab6d967288a", - 6, - "4c06bd2b6904f228a76c8560a3433bced9a8681d985a2848d407404d186b0280", - }, - { - "54873298ac2b5ba8591c125ae54931f5ea72040aee07b208d6135476fb5b9c0e", - 3, - "fd9597ca048212f90b543710afdb95e1bf560c20ca17161a8239fd64f212d42a", - }, - { - "7c30fbd363a74c17e1198f56b090b59bbb6c8755a74927a6cba7a54843506401", - 5, - "6cf4eb20f2447c77657fccb172d38c0aa91ea4ac446dc641fa463a6b5091fba7", - }, - { - "fb4529be3e027a3d1587d8a500b72f2d312e3577340ef5175f96d113be4c2ceb", - 8, - "da294df1f013d1e8ac3ec52805b979698971abb9a077a8bafcb688a4f261820f", - }, - } + name: "random sampling #1", + in1: "b75674dc9180d306c692163ac5e089f7cef166af99645c0c23568ab6d967288a", + in2: 6, + expected: "4c06bd2b6904f228a76c8560a3433bced9a8681d985a2848d407404d186b0280", + }, { + name: "random sampling #2", + in1: "54873298ac2b5ba8591c125ae54931f5ea72040aee07b208d6135476fb5b9c0e", + in2: 3, + expected: "fd9597ca048212f90b543710afdb95e1bf560c20ca17161a8239fd64f212d42a", + }, { + name: "random sampling #3", + in1: "7c30fbd363a74c17e1198f56b090b59bbb6c8755a74927a6cba7a54843506401", + in2: 5, + expected: "6cf4eb20f2447c77657fccb172d38c0aa91ea4ac446dc641fa463a6b5091fba7", + }, { + name: "random sampling #3", + in1: "fb4529be3e027a3d1587d8a500b72f2d312e3577340ef5175f96d113be4c2ceb", + in2: 8, + expected: "da294df1f013d1e8ac3ec52805b979698971abb9a077a8bafcb688a4f261820f", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { + for _, test := range tests { f := new(fieldVal).SetHex(test.in1).Normalize() expected := new(fieldVal).SetHex(test.expected).Normalize() result := f.MulInt(test.in2).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.MulInt #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: wrong result -- got: %v -- want: %v", test.name, + result, expected) continue } } } -// TestMul ensures that multiplying two field values via Mul works as expected. -func TestMul(t *testing.T) { +// TestFieldMul ensures that multiplying two field values via Mul and Mul2 works +// as expected. +func TestFieldMul(t *testing.T) { tests := []struct { + name string // test description in1 string // first hex encoded value in2 string // second hex encoded value to multiply with expected string // expected hex encoded value - }{ - {"0", "0", "0"}, - {"1", "0", "0"}, - {"0", "1", "0"}, - {"1", "1", "1"}, - // slightly over prime - { - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1ffff", - "1000", - "1ffff3d1", - }, - // secp256k1 prime-1 * 2 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - "2", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", - }, - // secp256k1 prime * 3 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "3", "0"}, - // secp256k1 prime-1 * 8 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - "8", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27", - }, - // Random samples. - { - "cfb81753d5ef499a98ecc04c62cb7768c2e4f1740032946db1c12e405248137e", - "58f355ad27b4d75fb7db0442452e732c436c1f7c5a7c4e214fa9cc031426a7d3", - "1018cd2d7c2535235b71e18db9cd98027386328d2fa6a14b36ec663c4c87282b", - }, - { - "26e9d61d1cdf3920e9928e85fa3df3e7556ef9ab1d14ec56d8b4fc8ed37235bf", - "2dfc4bbe537afee979c644f8c97b31e58be5296d6dbc460091eae630c98511cf", - "da85f48da2dc371e223a1ae63bd30b7e7ee45ae9b189ac43ff357e9ef8cf107a", - }, - { - "5db64ed5afb71646c8b231585d5b2bf7e628590154e0854c4c29920b999ff351", - "279cfae5eea5d09ade8e6a7409182f9de40981bc31c84c3d3dfe1d933f152e9a", - "2c78fbae91792dd0b157abe3054920049b1879a7cc9d98cfda927d83be411b37", - }, - { - "b66dfc1f96820b07d2bdbd559c19319a3a73c97ceb7b3d662f4fe75ecb6819e6", - "bf774aba43e3e49eb63a6e18037d1118152568f1a3ac4ec8b89aeb6ff8008ae1", - "c4f016558ca8e950c21c3f7fc15f640293a979c7b01754ee7f8b3340d4902ebb", - }, - } + }{{ + name: "zero * zero", + in1: "0", + in2: "0", + expected: "0", + }, { + name: "one * zero", + in1: "1", + in2: "0", + expected: "0", + }, { + name: "zero * one", + in1: "0", + in2: "1", + expected: "0", + }, { + name: "one * one", + in1: "1", + in2: "1", + expected: "1", + }, { + name: "slightly over prime", + in1: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1ffff", + in2: "1000", + expected: "1ffff3d1", + }, { + name: "secp256k1 prime-1 * 2", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: "2", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + }, { + name: "secp256k1 prime * 3", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + in2: "3", + expected: "0", + }, { + name: "secp256k1 prime * 3", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: "8", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27", + }, { + name: "random sampling #1", + in1: "cfb81753d5ef499a98ecc04c62cb7768c2e4f1740032946db1c12e405248137e", + in2: "58f355ad27b4d75fb7db0442452e732c436c1f7c5a7c4e214fa9cc031426a7d3", + expected: "1018cd2d7c2535235b71e18db9cd98027386328d2fa6a14b36ec663c4c87282b", + }, { + name: "random sampling #2", + in1: "26e9d61d1cdf3920e9928e85fa3df3e7556ef9ab1d14ec56d8b4fc8ed37235bf", + in2: "2dfc4bbe537afee979c644f8c97b31e58be5296d6dbc460091eae630c98511cf", + expected: "da85f48da2dc371e223a1ae63bd30b7e7ee45ae9b189ac43ff357e9ef8cf107a", + }, { + name: "random sampling #3", + in1: "5db64ed5afb71646c8b231585d5b2bf7e628590154e0854c4c29920b999ff351", + in2: "279cfae5eea5d09ade8e6a7409182f9de40981bc31c84c3d3dfe1d933f152e9a", + expected: "2c78fbae91792dd0b157abe3054920049b1879a7cc9d98cfda927d83be411b37", + }, { + name: "random sampling #4", + in1: "b66dfc1f96820b07d2bdbd559c19319a3a73c97ceb7b3d662f4fe75ecb6819e6", + in2: "bf774aba43e3e49eb63a6e18037d1118152568f1a3ac4ec8b89aeb6ff8008ae1", + expected: "c4f016558ca8e950c21c3f7fc15f640293a979c7b01754ee7f8b3340d4902ebb", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in1).Normalize() + for _, test := range tests { + f1 := new(fieldVal).SetHex(test.in1).Normalize() f2 := new(fieldVal).SetHex(test.in2).Normalize() expected := new(fieldVal).SetHex(test.expected).Normalize() - result := f.Mul(f2).Normalize() + + // Ensure multiplying the two values with the result going to another + // variable produces the expected result. + result := new(fieldVal).Mul2(f1, f2).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Mul #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + result, expected) + continue + } + + // Ensure multiplying the value to an existing field value produces the + // expected result. + f1.Mul(f2).Normalize() + if !f1.Equals(expected) { + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + f1, expected) continue } } } -// TestSquare ensures that squaring field values via Square works as expected. -func TestSquare(t *testing.T) { +// TestFieldSquare ensures that squaring field values via Square and SqualVal +// works as expected. +func TestFieldSquare(t *testing.T) { tests := []struct { + name string // test description in string // hex encoded value expected string // expected hex encoded value - }{ - // secp256k1 prime (aka 0) - {"0", "0"}, - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "0"}, - {"0", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"}, - // secp256k1 prime-1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1"}, - // secp256k1 prime-2 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", "4"}, - // Random sampling - { - "b0ba920360ea8436a216128047aab9766d8faf468895eb5090fc8241ec758896", - "133896b0b69fda8ce9f648b9a3af38f345290c9eea3cbd35bafcadf7c34653d3", - }, - { - "c55d0d730b1d0285a1599995938b042a756e6e8857d390165ffab480af61cbd5", - "cd81758b3f5877cbe7e5b0a10cebfa73bcbf0957ca6453e63ee8954ab7780bee", - }, - { - "e89c1f9a70d93651a1ba4bca5b78658f00de65a66014a25544d3365b0ab82324", - "39ffc7a43e5dbef78fd5d0354fb82c6d34f5a08735e34df29da14665b43aa1f", - }, - { - "7dc26186079d22bcbe1614aa20ae627e62d72f9be7ad1e99cac0feb438956f05", - "bf86bcfc4edb3d81f916853adfda80c07c57745b008b60f560b1912f95bce8ae", - }, - } + }{{ + name: "zero", + in: "0", + expected: "0", + }, { + name: "secp256k1 prime (direct val in with 0 out)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: "0", + }, { + name: "secp256k1 prime (0 in with direct val out)", + in: "0", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + }, { + name: "secp256k1 prime - 1", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + expected: "1", + }, { + name: "secp256k1 prime - 2", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + expected: "4", + }, { + name: "random sampling #1", + in: "b0ba920360ea8436a216128047aab9766d8faf468895eb5090fc8241ec758896", + expected: "133896b0b69fda8ce9f648b9a3af38f345290c9eea3cbd35bafcadf7c34653d3", + }, { + name: "random sampling #2", + in: "c55d0d730b1d0285a1599995938b042a756e6e8857d390165ffab480af61cbd5", + expected: "cd81758b3f5877cbe7e5b0a10cebfa73bcbf0957ca6453e63ee8954ab7780bee", + }, { + name: "random sampling #3", + in: "e89c1f9a70d93651a1ba4bca5b78658f00de65a66014a25544d3365b0ab82324", + expected: "39ffc7a43e5dbef78fd5d0354fb82c6d34f5a08735e34df29da14665b43aa1f", + }, { + name: "random sampling #4", + in: "7dc26186079d22bcbe1614aa20ae627e62d72f9be7ad1e99cac0feb438956f05", + expected: "bf86bcfc4edb3d81f916853adfda80c07c57745b008b60f560b1912f95bce8ae", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { + for _, test := range tests { f := new(fieldVal).SetHex(test.in).Normalize() expected := new(fieldVal).SetHex(test.expected).Normalize() - result := f.Square().Normalize() + + // Ensure squaring the value with the result going to another variable + // produces the expected result. + result := new(fieldVal).SquareVal(f).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Square #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + result, expected) + continue + } + + // Ensure self squaring an existing field value produces the expected + // result. + f.Square().Normalize() + if !f.Equals(expected) { + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + f, expected) continue } } @@ -1025,7 +1184,7 @@ func TestFieldSquareRootRandom(t *testing.T) { bigIntResult := new(big.Int).ModSqrt(bigIntVal, curveParams.P) bigIntHasSqrt := bigIntResult != nil - // Calculate the square root of the value using fieldVal. + // Calculate the square root of the value using a field value. var fValResult fieldVal fValHasSqrt := fValResult.SquareRootVal(fVal) @@ -1048,54 +1207,58 @@ func TestFieldSquareRootRandom(t *testing.T) { } } -// TestInverse ensures that finding the multiplicative inverse via Inverse works -// as expected. -func TestInverse(t *testing.T) { +// TestFieldInverse ensures that finding the multiplicative inverse via Inverse +// works as expected. +func TestFieldInverse(t *testing.T) { tests := []struct { + name string // test description in string // hex encoded value expected string // expected hex encoded value - }{ - // secp256k1 prime (aka 0) - {"0", "0"}, - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "0"}, - {"0", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"}, - // secp256k1 prime-1 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - }, - // secp256k1 prime-2 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", - "7fffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffe17", - }, - // Random sampling - { - "16fb970147a9acc73654d4be233cc48b875ce20a2122d24f073d29bd28805aca", - "987aeb257b063df0c6d1334051c47092b6d8766c4bf10c463786d93f5bc54354", - }, - { - "69d1323ce9f1f7b3bd3c7320b0d6311408e30281e273e39a0d8c7ee1c8257919", - "49340981fa9b8d3dad72de470b34f547ed9179c3953797d0943af67806f4bb6", - }, - { - "e0debf988ae098ecda07d0b57713e97c6d213db19753e8c95aa12a2fc1cc5272", - "64f58077b68af5b656b413ea366863f7b2819f8d27375d9c4d9804135ca220c2", - }, - { - "dcd394f91f74c2ba16aad74a22bb0ed47fe857774b8f2d6c09e28bfb14642878", - "fb848ec64d0be572a63c38fe83df5e7f3d032f60bf8c969ef67d36bf4ada22a9", - }, - } + }{{ + name: "zero", + in: "0", + expected: "0", + }, { + name: "secp256k1 prime (direct val in with 0 out)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: "0", + }, { + name: "secp256k1 prime (0 in with direct val out)", + in: "0", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + }, { + name: "secp256k1 prime - 1", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + }, { + name: "secp256k1 prime - 2", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + expected: "7fffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffe17", + }, { + name: "random sampling #1", + in: "16fb970147a9acc73654d4be233cc48b875ce20a2122d24f073d29bd28805aca", + expected: "987aeb257b063df0c6d1334051c47092b6d8766c4bf10c463786d93f5bc54354", + }, { + name: "random sampling #2", + in: "69d1323ce9f1f7b3bd3c7320b0d6311408e30281e273e39a0d8c7ee1c8257919", + expected: "49340981fa9b8d3dad72de470b34f547ed9179c3953797d0943af67806f4bb6", + }, { + name: "random sampling #3", + in: "e0debf988ae098ecda07d0b57713e97c6d213db19753e8c95aa12a2fc1cc5272", + expected: "64f58077b68af5b656b413ea366863f7b2819f8d27375d9c4d9804135ca220c2", + }, { + name: "random sampling #4", + in: "dcd394f91f74c2ba16aad74a22bb0ed47fe857774b8f2d6c09e28bfb14642878", + expected: "fb848ec64d0be572a63c38fe83df5e7f3d032f60bf8c969ef67d36bf4ada22a9", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { + for _, test := range tests { f := new(fieldVal).SetHex(test.in).Normalize() expected := new(fieldVal).SetHex(test.expected).Normalize() result := f.Inverse().Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Inverse #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: d wrong result\ngot: %v\nwant: %v", test.name, result, + expected) continue } } @@ -1201,7 +1364,7 @@ func TestFieldIsGtOrEqPrimeMinusOrderRandom(t *testing.T) { bigIntResult := bigIntVal.Cmp(bigPMinusN) >= 0 // Determine the value is greater than or equal to the prime minus the - // order using fieldVal. + // order using a field value. fValResult := fVal.IsGtOrEqPrimeMinusOrder() // Ensure they match.