• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OpShin / opshin / 18500088700

14 Oct 2025 02:33PM UTC coverage: 90.329%. First build
18500088700

Pull #549

github

nielstron
Fix formatting
Pull Request #549: Plutus V3 support

1294 of 1584 branches covered (81.69%)

Branch coverage included in aggregate %.

273 of 354 new or added lines in 16 files covered. (77.12%)

4740 of 5096 relevant lines covered (93.01%)

4.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.76
/opshin/rewrite/rewrite_import_bls12_381.py
1
import ast
5✔
2
import typing
5✔
3
from _ast import ImportFrom, AST, Store, Assign, Name
5✔
4
from dataclasses import dataclass
5✔
5
from enum import Enum, auto
5✔
6

7
import uplc.ast
5✔
8

9
import pluthon as plt
5✔
10

11
from frozenlist2 import frozenlist
5✔
12

13
from ..typed_ast import *
5✔
14
from ..type_impls import (
5✔
15
    ClassType,
16
    InstanceType,
17
    ByteStringInstanceType,
18
    FunctionType,
19
    AtomicType,
20
    UnitType,
21
    IntegerType,
22
)
23
from ..util import CompilingNodeTransformer, force_params, OVar, OLambda
5✔
24

25
"""
4✔
26
Checks that there was an import of dataclass if there are any class definitions
27
"""
28

29

30
@dataclass(frozen=True, unsafe_hash=True)
5✔
31
class BLS12381G1ElementType(ClassType):
5✔
32
    def python_type(self):
5✔
33
        return "BLS12381G1Element"
5✔
34

35
    def constr_type(self):
5✔
36
        return InstanceType(
5✔
37
            FunctionType([BLS12381G1ElementInstance], BLS12381G1ElementInstance)
38
        )
39

40
    def constr(self) -> plt.AST:
5✔
NEW
41
        return OLambda(["x"], OVar("x"))
×
42

43
    def cmp(self, op: ast.cmpop, o: "Type") -> plt.AST:
5✔
44
        if isinstance(op, ast.Eq) and isinstance(o, BLS12381G1ElementType):
5✔
45
            return plt.BuiltIn(uplc.ast.BuiltInFun.Bls12_381_G1_Equal)
5✔
46
        raise NotImplementedError(
47
            f"Comparison {op.__class__.__name__} not implemented for {self.python_type()} and {o.python_type()}"
48
        )
49

50
    def _binop_return_type(self, binop: ast.operator, other: "Type") -> "Type":
5✔
51
        if isinstance(other, InstanceType):
5!
52
            other = other.typ
5✔
53
            if isinstance(other, BLS12381G1ElementType):
5✔
54
                if isinstance(binop, (ast.Add, ast.Sub)):
5!
55
                    return BLS12381G1ElementType()
5✔
56
            if isinstance(other, IntegerType):
5!
57
                if isinstance(binop, ast.Mult):
5!
58
                    return BLS12381G1ElementType()
5✔
NEW
59
        return super()._binop_return_type(binop, other)
×
60

61
    def _binop_bin_fun(self, binop: ast.operator, other: "TypedAST"):
5✔
62
        if isinstance(other.typ, InstanceType):
5!
63
            other = other.typ.typ
5✔
64
            if isinstance(other, BLS12381G1ElementType):
5✔
65
                if isinstance(binop, ast.Add):
5!
66
                    return plt.Bls12_381_G1_Add
5✔
NEW
67
                if isinstance(binop, ast.Sub):
×
NEW
68
                    return lambda x, y: plt.Bls12_381_G1_Add(x, plt.Bls12_381_G1_Neg(y))
×
69
            if isinstance(other, IntegerType):
5!
70
                if isinstance(binop, ast.Mult):
5!
71
                    return lambda x, y: plt.Bls12_381_G1_ScalarMul(y, x)
5✔
NEW
72
        return super()._binop_bin_fun(binop, other)
×
73

74
    def _rbinop_return_type(self, binop: ast.operator, other: "Type") -> "Type":
5✔
75
        if isinstance(other, InstanceType):
5!
76
            other = other.typ
5✔
77
            if isinstance(other, IntegerType):
5!
78
                if isinstance(binop, ast.Mult):
5!
79
                    return BLS12381G1ElementType()
5✔
NEW
80
        return super()._rbinop_return_type(binop, other)
×
81

82
    def _rbinop_bin_fun(self, binop: ast.operator, other: "TypedAST"):
5✔
83
        if isinstance(other.typ, InstanceType):
5!
84
            other = other.typ.typ
5✔
85
            if isinstance(other, IntegerType):
5!
86
                if isinstance(binop, ast.Mult):
5!
87
                    return plt.Bls12_381_G1_ScalarMul
5✔
NEW
88
        return super()._rbinop_bin_fun(binop, other)
×
89

90
    def attribute_type(self, attr) -> "Type":
5✔
91
        if attr == "compress":
5!
92
            return InstanceType(FunctionType([], ByteStringInstanceType))
5✔
NEW
93
        return super().attribute_type(attr)
×
94

95
    def attribute(self, attr) -> plt.AST:
5✔
96
        if attr == "compress":
5!
97
            return OLambda(["x", "_"], plt.Bls12_381_G1_Compress(OVar("x")))
5✔
NEW
98
        return super().attribute(attr)
×
99

100
    def _unop_return_type(self, unop: ast.unaryop) -> "Type":
5✔
101
        if isinstance(unop, (ast.USub, ast.UAdd)):
5!
102
            return BLS12381G1ElementType()
5✔
NEW
103
        return super()._unop_return_type(unop)
×
104

105
    def _unop_fun(self, unop: ast.unaryop):
5✔
106
        if isinstance(unop, ast.USub):
5!
107
            return plt.Bls12_381_G1_Neg
5✔
NEW
108
        if isinstance(unop, ast.UAdd):
×
NEW
109
            return lambda x: x
×
NEW
110
        return super()._unop_fun(unop)
×
111

112
    def __ge__(self, other):
5✔
113
        return isinstance(other, BLS12381G1ElementType)
5✔
114

115

116
@dataclass(frozen=True, unsafe_hash=True)
5✔
117
class BLS12381G2ElementType(ClassType):
5✔
118
    def python_type(self):
5✔
119
        return "BLS12381G2Element"
5✔
120

121
    def constr_type(self):
5✔
122
        return InstanceType(
5✔
123
            FunctionType([BLS12381G2ElementInstance], BLS12381G2ElementInstance)
124
        )
125

126
    def constr(self) -> plt.AST:
5✔
NEW
127
        return OLambda(["x"], OVar("x"))
×
128

129
    def cmp(self, op: ast.cmpop, o: "Type") -> plt.AST:
5✔
130
        if isinstance(op, ast.Eq) and isinstance(o, BLS12381G2ElementType):
5✔
131
            return plt.BuiltIn(uplc.ast.BuiltInFun.Bls12_381_G2_Equal)
5✔
132
        raise NotImplementedError(
133
            f"Comparison {op.__class__.__name__} not implemented for {self.python_type()} and {o.python_type()}"
134
        )
135

136
    def _binop_return_type(self, binop: ast.operator, other: "Type") -> "Type":
5✔
137
        if isinstance(other, InstanceType):
5!
138
            other = other.typ
5✔
139
            if isinstance(other, BLS12381G2ElementType):
5✔
140
                if isinstance(binop, (ast.Add, ast.Sub)):
5!
141
                    return BLS12381G2ElementType()
5✔
142
            if isinstance(other, IntegerType):
5!
143
                if isinstance(binop, ast.Mult):
5!
144
                    return BLS12381G2ElementType()
5✔
NEW
145
        return super()._binop_return_type(binop, other)
×
146

147
    def _binop_bin_fun(self, binop: ast.operator, other: "TypedAST"):
5✔
148
        if isinstance(other.typ, InstanceType):
5!
149
            other = other.typ.typ
5✔
150
            if isinstance(other, BLS12381G2ElementType):
5✔
151
                if isinstance(binop, ast.Add):
5!
152
                    return plt.Bls12_381_G2_Add
5✔
NEW
153
                if isinstance(binop, ast.Sub):
×
NEW
154
                    return lambda x, y: plt.Bls12_381_G2_Add(x, plt.Bls12_381_G2_Neg(y))
×
155
            if isinstance(other, IntegerType):
5!
156
                if isinstance(binop, ast.Mult):
5!
157
                    return lambda x, y: plt.Bls12_381_G2_ScalarMul(y, x)
5✔
NEW
158
        return super()._binop_bin_fun(binop, other)
×
159

160
    def _rbinop_return_type(self, binop: ast.operator, other: "Type") -> "Type":
5✔
161
        if isinstance(other, InstanceType):
5!
162
            other = other.typ
5✔
163
            if isinstance(other, IntegerType):
5!
164
                if isinstance(binop, ast.Mult):
5!
165
                    return BLS12381G2ElementType()
5✔
NEW
166
        return super()._rbinop_return_type(binop, other)
×
167

168
    def _rbinop_bin_fun(self, binop: ast.operator, other: "TypedAST"):
5✔
169
        if isinstance(other.typ, InstanceType):
5!
170
            other = other.typ.typ
5✔
171
            if isinstance(other, IntegerType):
5!
172
                if isinstance(binop, ast.Mult):
5!
173
                    return plt.Bls12_381_G2_ScalarMul
5✔
NEW
174
        return super()._rbinop_bin_fun(binop, other)
×
175

176
    def attribute_type(self, attr) -> "Type":
5✔
177
        if attr == "compress":
5!
178
            return InstanceType(FunctionType([], ByteStringInstanceType))
5✔
NEW
179
        return super().attribute_type(attr)
×
180

181
    def attribute(self, attr) -> plt.AST:
5✔
182
        if attr == "compress":
5!
183
            return OLambda(["x", "_"], plt.Bls12_381_G2_Compress(OVar("x")))
5✔
NEW
184
        return super().attribute(attr)
×
185

186
    def _unop_return_type(self, unop: ast.unaryop) -> "Type":
5✔
187
        if isinstance(unop, (ast.USub, ast.UAdd)):
5!
188
            return BLS12381G2ElementType()
5✔
NEW
189
        return super()._unop_return_type(unop)
×
190

191
    def _unop_fun(self, unop: ast.unaryop):
5✔
192
        if isinstance(unop, ast.USub):
5!
193
            return plt.Bls12_381_G2_Neg
5✔
NEW
194
        if isinstance(unop, ast.UAdd):
×
NEW
195
            return lambda x: x
×
NEW
196
        return super()._unop_fun(unop)
×
197

198
    def __ge__(self, other):
5✔
199
        return isinstance(other, BLS12381G2ElementType)
5✔
200

201

202
@dataclass(frozen=True, unsafe_hash=True)
5✔
203
class BLS12381MlresultType(ClassType):
5✔
204
    def python_type(self):
5✔
205
        return "BLS12381MillerLoopResult"
5✔
206

207
    def constr_type(self):
5✔
208
        return InstanceType(
5✔
209
            FunctionType([BLS12381MlresultInstance], BLS12381MlresultInstance)
210
        )
211

212
    def constr(self) -> plt.AST:
5✔
NEW
213
        return OLambda(["x"], OVar("x"))
×
214

215
    def _binop_return_type(self, binop: ast.operator, other: "Type") -> "Type":
5✔
216
        if isinstance(other, InstanceType):
5!
217
            other = other.typ
5✔
218
            if isinstance(other, BLS12381MlresultType):
5!
219
                if isinstance(binop, ast.Mult):
5!
220
                    return BLS12381MlresultType()
5✔
NEW
221
        return super()._binop_return_type(binop, other)
×
222

223
    def _binop_bin_fun(self, binop: ast.operator, other: "TypedAST"):
5✔
224
        if isinstance(other.typ, InstanceType):
5!
225
            other = other.typ.typ
5✔
226
            if isinstance(other, BLS12381MlresultType):
5!
227
                if isinstance(binop, ast.Mult):
5!
228
                    return plt.Bls12_381_MulMlResult
5✔
NEW
229
        return super()._binop_bin_fun(binop, other)
×
230

231
    def __ge__(self, other):
5✔
232
        return isinstance(other, BLS12381MlresultType)
5✔
233

234

235
BLS12381G1ElementInstance = InstanceType(BLS12381G1ElementType())
5✔
236
BLS12381G2ElementInstance = InstanceType(BLS12381G2ElementType())
5✔
237
BLS12381MlresultInstance = InstanceType(BLS12381MlresultType())
5✔
238

239
BLS12_381_ENTRIES = {
5✔
240
    x.python_type(): x
241
    for x in (
242
        BLS12381G1ElementType(),
243
        BLS12381G2ElementType(),
244
        BLS12381MlresultType(),
245
    )
246
}
247

248

249
class RewriteImportBLS12381(CompilingNodeTransformer):
5✔
250
    step = "Resolving imports and usage of std.bls12_381"
5✔
251

252
    def visit_ImportFrom(self, node: ImportFrom) -> typing.Union[typing.List[AST], AST]:
5✔
253
        if node.module != "opshin.std.bls12_381":
5✔
254
            return node
5✔
255
        additional_assigns = []
5✔
256
        for n in node.names:
5✔
257
            imported_type = BLS12_381_ENTRIES.get(n.name)
5✔
258
            assert (
5✔
259
                imported_type is not None
260
            ), f"Unsupported type import from bls12_381 '{n.name}"
261
            imported_name = n.name if n.asname is None else n.asname
5✔
262
            additional_assigns.append(
5✔
263
                Assign(
264
                    targets=[Name(id=imported_name, ctx=Store())],
265
                    value=RawPlutoExpr(expr=plt.Unit(), typ=imported_type),
266
                )
267
            )
268
        return additional_assigns
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc