types.go raw
1 // Package avx provides AVX2-accelerated secp256k1 operations using 128-bit limbs.
2 //
3 // This implementation uses 128-bit limbs stored in 256-bit AVX2 registers:
4 // - Scalar: 256-bit value as 2×128-bit limbs (fits in 1 YMM register)
5 // - FieldElement: 256-bit value as 2×128-bit limbs (fits in 1 YMM register)
6 // - AffinePoint: 512-bit (x,y) as 2×256-bit (fits in 2 YMM registers)
7 // - JacobianPoint: 768-bit (x,y,z) as 3×256-bit (fits in 3 YMM registers)
8 package avx
9
10 // Uint128 represents a 128-bit unsigned integer as two 64-bit limbs.
11 // This is the fundamental building block for AVX2 operations.
12 // In AVX2 assembly, two Uint128 values fit in a single YMM register.
13 type Uint128 struct {
14 Lo, Hi uint64 // Lo + Hi<<64
15 }
16
17 // Scalar represents a 256-bit scalar value modulo the secp256k1 group order.
18 // Uses 2×128-bit limbs for efficient AVX2 processing.
19 // The entire scalar fits in a single YMM register.
20 type Scalar struct {
21 D [2]Uint128 // D[0] is low 128 bits, D[1] is high 128 bits
22 }
23
24 // FieldElement represents a field element modulo the secp256k1 field prime.
25 // Uses 2×128-bit limbs for efficient AVX2 processing.
26 // The entire field element fits in a single YMM register.
27 type FieldElement struct {
28 N [2]Uint128 // N[0] is low 128 bits, N[1] is high 128 bits
29 }
30
31 // AffinePoint represents a point on the secp256k1 curve in affine coordinates.
32 // Uses 2 YMM registers (one for X, one for Y).
33 type AffinePoint struct {
34 X, Y FieldElement
35 Infinity bool
36 }
37
38 // JacobianPoint represents a point in Jacobian coordinates (X, Y, Z).
39 // Affine coordinates are (X/Z², Y/Z³).
40 // Uses 3 YMM registers (one each for X, Y, Z).
41 type JacobianPoint struct {
42 X, Y, Z FieldElement
43 Infinity bool
44 }
45
46 // Constants for secp256k1
47
48 // Group order n = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
49 var (
50 ScalarN = Scalar{
51 D: [2]Uint128{
52 {Lo: 0xBFD25E8CD0364141, Hi: 0xBAAEDCE6AF48A03B}, // low 128 bits
53 {Lo: 0xFFFFFFFFFFFFFFFE, Hi: 0xFFFFFFFFFFFFFFFF}, // high 128 bits
54 },
55 }
56
57 // 2^256 - n (used for reduction)
58 ScalarNC = Scalar{
59 D: [2]Uint128{
60 {Lo: 0x402DA1732FC9BEBF, Hi: 0x4551231950B75FC4}, // low 128 bits
61 {Lo: 0x0000000000000001, Hi: 0x0000000000000000}, // high 128 bits
62 },
63 }
64
65 // n/2 (for checking if scalar is high)
66 ScalarNHalf = Scalar{
67 D: [2]Uint128{
68 {Lo: 0xDFE92F46681B20A0, Hi: 0x5D576E7357A4501D}, // low 128 bits
69 {Lo: 0xFFFFFFFFFFFFFFFF, Hi: 0x7FFFFFFFFFFFFFFF}, // high 128 bits
70 },
71 }
72
73 ScalarZero = Scalar{}
74 ScalarOne = Scalar{D: [2]Uint128{{Lo: 1, Hi: 0}, {Lo: 0, Hi: 0}}}
75 )
76
77 // Field prime p = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
78 var (
79 FieldP = FieldElement{
80 N: [2]Uint128{
81 {Lo: 0xFFFFFFFEFFFFFC2F, Hi: 0xFFFFFFFFFFFFFFFF}, // low 128 bits
82 {Lo: 0xFFFFFFFFFFFFFFFF, Hi: 0xFFFFFFFFFFFFFFFF}, // high 128 bits
83 },
84 }
85
86 // 2^256 - p = 2^32 + 977 = 0x1000003D1
87 FieldPC = FieldElement{
88 N: [2]Uint128{
89 {Lo: 0x1000003D1, Hi: 0}, // low 128 bits
90 {Lo: 0, Hi: 0}, // high 128 bits
91 },
92 }
93
94 FieldZero = FieldElement{}
95 FieldOne = FieldElement{N: [2]Uint128{{Lo: 1, Hi: 0}, {Lo: 0, Hi: 0}}}
96 )
97
98 // Generator point G for secp256k1
99 var (
100 GeneratorX = FieldElement{
101 N: [2]Uint128{
102 {Lo: 0x59F2815B16F81798, Hi: 0x029BFCDB2DCE28D9},
103 {Lo: 0x55A06295CE870B07, Hi: 0x79BE667EF9DCBBAC},
104 },
105 }
106
107 GeneratorY = FieldElement{
108 N: [2]Uint128{
109 {Lo: 0x9C47D08FFB10D4B8, Hi: 0xFD17B448A6855419},
110 {Lo: 0x5DA4FBFC0E1108A8, Hi: 0x483ADA7726A3C465},
111 },
112 }
113
114 Generator = AffinePoint{
115 X: GeneratorX,
116 Y: GeneratorY,
117 Infinity: false,
118 }
119 )
120