LCOV - code coverage report
Current view: top level - crypto/evm/utils - utils.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 83.1 % 59 49
Test Date: 2025-01-30 01:10:00 Functions: - 0 0

            Line data    Source code
       1              : import 'dart:typed_data';
       2              : import 'package:pointycastle/ecc/api.dart';
       3              : import 'package:pointycastle/ecc/curves/secp256k1.dart';
       4              : import 'package:pointycastle/src/utils.dart' as p_utils;
       5              : import 'package:walletkit_dart/src/crypto/evm/entities/raw_transaction/signature.dart';
       6              : import 'package:walletkit_dart/src/crypto/utxo/utils/eurocoin_signing.dart';
       7              : 
       8           12 : final params = ECCurve_secp256k1();
       9              : 
      10            3 : Uint8List privateKeyToPublic(BigInt privateKey) {
      11            9 :   final p = (params.G * privateKey)!;
      12              :   //skip the type flag, https://github.com/ethereumjs/ethereumjs-util/blob/master/index.js#L319
      13            9 :   return Uint8List.view(p.getEncoded(false).buffer, 1);
      14              : }
      15              : 
      16            4 : BigInt bytesToUnsignedInt(Uint8List bytes) {
      17            4 :   return p_utils.decodeBigIntWithSign(1, bytes);
      18              : }
      19              : 
      20            2 : Uint8List recoverPublicKey(
      21              :   Uint8List payload,
      22              :   Signature signature, {
      23              :   bool hasSignatureYParity = false,
      24              : }) {
      25            6 :   final r = padUint8ListTo32(p_utils.encodeBigIntAsUnsigned(signature.r));
      26            6 :   final s = padUint8ListTo32(p_utils.encodeBigIntAsUnsigned(signature.s));
      27              : 
      28            6 :   assert(r.length == 32);
      29            6 :   assert(s.length == 32);
      30              : 
      31            2 :   final v = signature.v;
      32              :   int chainId = 0;
      33              :   int recoveryId;
      34              : 
      35              :   // Type 1 and Type 2 Transactions
      36              :   if (hasSignatureYParity) {
      37            1 :     recoveryId = signature.v; // Since V is the signature parity which is 0 or 1
      38              :   } else {
      39              :     // Handle both pre-EIP-155 and EIP-155 v values
      40            4 :     if (v == 27 || v == 28) {
      41            1 :       recoveryId = v - 27;
      42              :     } else {
      43            2 :       chainId = (v - 35) ~/ 2;
      44            3 :       recoveryId = v - (2 * chainId + 35);
      45              :     }
      46              :   }
      47              : 
      48            4 :   if (recoveryId != 0 && recoveryId != 1) {
      49            0 :     throw Exception('Invalid recovery id');
      50              :   }
      51              : 
      52            6 :   final sig = ECSignature(signature.r, signature.s);
      53              : 
      54            4 :   final pubKey = _recoverFromSignature(recoveryId, sig, payload, params);
      55              : 
      56              :   if (pubKey == null) {
      57            0 :     throw Exception('Failed to recover public key');
      58              :   }
      59              : 
      60            2 :   return unsignedIntToBytes(pubKey);
      61              : }
      62              : 
      63            2 : ECPoint _decompressKey(BigInt xBN, bool yBit, ECCurve c) {
      64            2 :   List<int> x9IntegerToBytes(BigInt s, int qLength) {
      65              :     //https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java#L45
      66            2 :     final bytes = p_utils.encodeBigInt(s);
      67              : 
      68            4 :     if (qLength < bytes.length) {
      69            0 :       return bytes.sublist(0, bytes.length - qLength);
      70            4 :     } else if (qLength > bytes.length) {
      71            1 :       final tmp = List<int>.filled(qLength, 0);
      72              : 
      73            2 :       final offset = qLength - bytes.length;
      74            3 :       for (var i = 0; i < bytes.length; i++) {
      75            3 :         tmp[i + offset] = bytes[i];
      76              :       }
      77              : 
      78              :       return tmp;
      79              :     }
      80              : 
      81              :     return bytes;
      82              :   }
      83              : 
      84           10 :   final compEnc = x9IntegerToBytes(xBN, 1 + ((c.fieldSize + 7) ~/ 8));
      85            2 :   compEnc[0] = yBit ? 0x03 : 0x02;
      86            2 :   return c.decodePoint(compEnc)!;
      87              : }
      88              : 
      89            2 : BigInt? _recoverFromSignature(
      90              :   int recId,
      91              :   ECSignature sig,
      92              :   Uint8List msg,
      93              :   ECDomainParameters params,
      94              : ) {
      95            2 :   final n = params.n;
      96            4 :   final i = BigInt.from(recId ~/ 2);
      97            6 :   final x = sig.r + (i * n);
      98              : 
      99              :   //Parameter q of curve
     100            2 :   final prime = BigInt.parse(
     101              :     'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f',
     102              :     radix: 16,
     103              :   );
     104            4 :   if (x.compareTo(prime) >= 0) return null;
     105              : 
     106            8 :   final R = _decompressKey(x, (recId & 1) == 1, params.curve);
     107            4 :   if (!(R * n)!.isInfinity) return null;
     108              : 
     109            2 :   final e = bytesToUnsignedInt(msg);
     110              : 
     111            6 :   final eInv = (BigInt.zero - e) % n;
     112            4 :   final rInv = sig.r.modInverse(n);
     113            6 :   final srInv = (rInv * sig.s) % n;
     114            4 :   final eInvrInv = (rInv * eInv) % n;
     115              : 
     116            8 :   final q = (params.G * eInvrInv)! + (R * srInv);
     117              : 
     118            2 :   final bytes = q!.getEncoded(false);
     119            4 :   return bytesToUnsignedInt(bytes.sublist(1));
     120              : }
     121              : 
     122            0 : int extractChainId(int v) {
     123              :   // Ensure `v` is a BigInt
     124            0 :   if (v >= 35) {
     125            0 :     return (v - 35) >> 1;
     126              :   } else {
     127            0 :     throw ArgumentError("v parameter does not contain a chain id");
     128              :   }
     129              : }
     130              : 
     131              : /// Given a byte array computes its compressed version and returns it as a byte array,
     132              : /// including the leading 02 or 03
     133            0 : Uint8List compressPublicKey(Uint8List compressedPubKey) {
     134            0 :   return Uint8List.view(
     135            0 :     params.curve.decodePoint(compressedPubKey)!.getEncoded(true).buffer,
     136              :   );
     137              : }
        

Generated by: LCOV version 2.0-1