@@ -240,6 +240,63 @@ ExecutionResult identity_execute(const uint8_t* input, size_t input_size, uint8_
240
240
return {EVMC_SUCCESS, input_size};
241
241
}
242
242
243
+ ExecutionResult ecpairing_execute (const uint8_t * input, size_t input_size, uint8_t * output,
244
+ [[maybe_unused]] size_t output_size) noexcept
245
+ {
246
+ assert (output_size >= 32 );
247
+
248
+ const auto pair_size = 192 ;
249
+
250
+ if (input_size % pair_size != 0 )
251
+ return {EVMC_PRECOMPILE_FAILURE, 0 };
252
+
253
+ const auto pair_count = input_size / pair_size;
254
+
255
+ if (pair_count > 0 )
256
+ {
257
+ auto input_idx = input;
258
+
259
+ std::vector<evmmax::bn254::Point > vG1 (pair_count);
260
+ std::vector<evmmax::bn254::ExtPoint> vG2 (pair_count);
261
+
262
+ for (size_t i = 0 ; i < pair_count; ++i)
263
+ {
264
+ const evmmax::bn254::Point p = {
265
+ intx::be::unsafe::load<intx::uint256>(input_idx),
266
+ intx::be::unsafe::load<intx::uint256>(input_idx + 32 ),
267
+ };
268
+
269
+ const evmmax::bn254::ExtPoint q = {
270
+ {intx::be::unsafe::load<intx::uint256>(input_idx + 96 ),
271
+ intx::be::unsafe::load<intx::uint256>(input_idx + 64 )},
272
+ {intx::be::unsafe::load<intx::uint256>(input_idx + 160 ),
273
+ intx::be::unsafe::load<intx::uint256>(input_idx + 128 )},
274
+ };
275
+
276
+ vG1[i] = p;
277
+ vG2[i] = q;
278
+
279
+ input_idx += pair_size;
280
+ }
281
+
282
+ const auto res = evmmax::bn254::pairing (vG2, vG1);
283
+
284
+ if (res.has_value ())
285
+ {
286
+ intx::be::unsafe::store (output, res.value () ? intx::uint256{1 } : intx::uint256{0 });
287
+ return {EVMC_SUCCESS, 64 };
288
+ }
289
+ else
290
+ return {EVMC_PRECOMPILE_FAILURE, 0 };
291
+ }
292
+ else
293
+ {
294
+ intx::be::unsafe::store (output, intx::uint256{1 });
295
+ return {EVMC_SUCCESS, 32 };
296
+ }
297
+ }
298
+
299
+
243
300
namespace
244
301
{
245
302
struct PrecompileTraits
0 commit comments