ethereum.crypto.elliptic_curve

Elliptic Curves ^^^^^^^^^^^^^^^

SECP256K1N

15
SECP256K1N = U256(
16
    0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
17
)

F

19
F = TypeVar("F", bound=Field)

T

20
T = TypeVar("T", bound="EllipticCurve")

secp256k1_recover

Recovers the public key from a given signature.

Parameters

r : TODO s : TODO v : TODO msg_hash : Hash of the message being recovered.

Returns

public_key : ethereum.base_types.Bytes Recovered public key.

def secp256k1_recover(r: U256, ​​s: U256, ​​v: U256, ​​msg_hash: Hash32) -> Bytes:
24
    """
25
    Recovers the public key from a given signature.
26
27
    Parameters
28
    ----------
29
    r :
30
        TODO
31
    s :
32
        TODO
33
    v :
34
        TODO
35
    msg_hash :
36
        Hash of the message being recovered.
37
38
    Returns
39
    -------
40
    public_key : `ethereum.base_types.Bytes`
41
        Recovered public key.
42
    """
43
    r_bytes = r.to_be_bytes32()
44
    s_bytes = s.to_be_bytes32()
45
46
    signature = bytearray([0] * 65)
47
    signature[32 - len(r_bytes) : 32] = r_bytes
48
    signature[64 - len(s_bytes) : 64] = s_bytes
49
    signature[64] = v
50
    public_key = coincurve.PublicKey.from_signature_and_message(
51
        bytes(signature), msg_hash, hasher=None
52
    )
53
    public_key = public_key.format(compressed=False)[1:]
54
    return public_key

EllipticCurve

Superclass for integers modulo a prime. Not intended to be used directly, but rather to be subclassed.

class EllipticCurve:

__slots__

63
    __slots__ = ("x", "y")

FIELD

65
    FIELD: Type[F]

A

66
    A: F

B

67
    B: F

x

69
    x: F

y

70
    y: F

__new__

Make new point on the curve. The point is not checked to see if it is on the curve.

def __new__(cls: Type[T], ​​x: F, ​​y: F) -> T:
73
        """
74
        Make new point on the curve. The point is not checked to see if it is
75
        on the curve.
76
        """
77
        res = object.__new__(cls)
78
        res.x = x
79
        res.y = y
80
        return res

__init__

Checks if the point is on the curve. To skip this check call __new__() directly.

def __init__(self, ​​x: F, ​​y: F) -> None:
83
        """
84
        Checks if the point is on the curve. To skip this check call
85
        `__new__()` directly.
86
        """
87
        if (
88
            x != self.FIELD.zero() or y != self.FIELD.zero()
89
        ) and y ** 2 - x**3 - self.A * x - self.B != self.FIELD.zero():
90
            raise ValueError("Point not on curve")

__eq__

Test two points for equality.

def __eq__(self, ​​other: object) -> bool:
93
        """
94
        Test two points for equality.
95
        """
96
        if not isinstance(other, type(self)):
97
            return False
98
        return self.x == other.x and self.y == other.y

__str__

Stringify a point as its coordinates.

def __str__(self) -> str:
101
        """
102
        Stringify a point as its coordinates.
103
        """
104
        return str((self.x, self.y))

point_at_infinity

Return the point at infinity. This is the identity element of the group operation.

The point at infinity doesn't actually have coordinates so we use (0, 0) (which isn't on the curve) to represent it.

106
    @classmethod
def point_at_infinity(cls: Type[T]) -> T:
108
        """
109
        Return the point at infinity. This is the identity element of the group
110
        operation.
111
112
        The point at infinity doesn't actually have coordinates so we use
113
        `(0, 0)` (which isn't on the curve) to represent it.
114
        """
115
        return cls.__new__(cls, cls.FIELD.zero(), cls.FIELD.zero())

double

Add a point to itself.

def double(self: T) -> T:
118
        """
119
        Add a point to itself.
120
        """
121
        x, y, F = self.x, self.y, self.FIELD
122
        if x == 0 and y == 0:
123
            return self
124
        lam = (F.from_int(3) * x**2 + self.A) / (F.from_int(2) * y)
125
        new_x = lam**2 - x - x
126
        new_y = lam * (x - new_x) - y
127
        return self.__new__(type(self), new_x, new_y)

__add__

Add two points together.

def __add__(self: T, ​​other: T) -> T:
130
        """
131
        Add two points together.
132
        """
133
        ZERO = self.FIELD.zero()
134
        self_x, self_y, other_x, other_y = self.x, self.y, other.x, other.y
135
        if self_x == ZERO and self_y == ZERO:
136
            return other
137
        if other_x == ZERO and other_y == ZERO:
138
            return self
139
        if self_x == other_x:
140
            if self_y == other_y:
141
                return self.double()
142
            else:
143
                return self.point_at_infinity()
144
        lam = (other_y - self_y) / (other_x - self_x)
145
        x = lam**2 - self_x - other_x
146
        y = lam * (self_x - x) - self_y
147
        return self.__new__(type(self), x, y)

mul_by

Multiply self by n using the double and add algorithm.

def mul_by(self: T, ​​n: int) -> T:
150
        """
151
        Multiply `self` by `n` using the double and add algorithm.
152
        """
153
        res = self.__new__(type(self), self.FIELD.zero(), self.FIELD.zero())
154
        s = self
155
        while n != 0:
156
            if n % 2 == 1:
157
                res = res + s
158
            s = s + s
159
            n //= 2
160
        return res