|
1 | 1 | # secp256k1_compat.py: Compatibility layer for secp256k1.py to use MicroPython's usecp256k1 module |
2 | | -# Mimics cffi's ffi and lib objects |
3 | 2 |
|
4 | | -import usecp256k1 # Your MicroPython C module |
| 3 | +import usecp256k1 |
5 | 4 |
|
6 | 5 | # Constants (from libsecp256k1) |
7 | 6 | SECP256K1_CONTEXT_SIGN = 1 << 8 # 256 |
|
11 | 10 |
|
12 | 11 | # Dummy ffi class to mimic cffi |
13 | 12 | class FFI: |
| 13 | + NULL = None # Mimic cffi's NULL pointer |
| 14 | + |
14 | 15 | def new(self, type_str): |
15 | | - # For 'unsigned char[74]' or 'size_t *' |
16 | | - if 'unsigned char' in type_str: |
| 16 | + if 'char' in type_str: |
17 | 17 | size = int(type_str.split('[')[1].rstrip(']')) |
18 | 18 | return bytearray(size) |
19 | 19 | elif 'size_t *' in type_str: |
20 | | - return [0] # Simulate pointer to size_t |
| 20 | + return [0] |
21 | 21 | raise ValueError(f"Unsupported ffi type: {type_str}") |
22 | 22 |
|
23 | 23 | def buffer(self, obj, size=None): |
24 | | - # Return bytes from bytearray or slice |
25 | 24 | if isinstance(obj, list): |
26 | 25 | return bytes(obj) |
27 | 26 | return bytes(obj[:size] if size is not None else obj) |
28 | 27 |
|
| 28 | + def memmove(self, dst, src, n): |
| 29 | + if isinstance(src, bytes): |
| 30 | + src = bytearray(src) |
| 31 | + dst[:n] = src[:n] |
| 32 | + |
| 33 | + def callback(self, signature): |
| 34 | + # Simplified decorator to mark functions without setting attributes |
| 35 | + def decorator(func): |
| 36 | + return func # Return func as-is |
| 37 | + return decorator |
| 38 | + |
29 | 39 | # Dummy lib class to map to usecp256k1 functions |
30 | 40 | class Lib: |
31 | | - # Constants |
32 | 41 | SECP256K1_EC_COMPRESSED = SECP256K1_EC_COMPRESSED |
33 | 42 | SECP256K1_EC_UNCOMPRESSED = SECP256K1_EC_UNCOMPRESSED |
34 | 43 | SECP256K1_CONTEXT_SIGN = SECP256K1_CONTEXT_SIGN |
35 | 44 | SECP256K1_CONTEXT_VERIFY = SECP256K1_CONTEXT_VERIFY |
36 | 45 |
|
37 | 46 | def secp256k1_context_create(self, flags): |
38 | | - # Context is managed by usecp256k1, return dummy object |
39 | 47 | return object() |
40 | 48 |
|
41 | 49 | def secp256k1_ecdsa_signature_serialize_der(self, ctx, output, outputlen, raw_sig): |
42 | | - # Call usecp256k1_ecdsa_signature_serialize_der |
43 | 50 | try: |
44 | 51 | result = usecp256k1.usecp256k1_ecdsa_signature_serialize_der(raw_sig) |
45 | 52 | if result is None: |
46 | | - return 0 # Mimic libsecp256k1 failure |
47 | | - # Copy result to output buffer |
| 53 | + return 0 |
48 | 54 | output[:len(result)] = result |
49 | 55 | outputlen[0] = len(result) |
50 | | - return 1 # Mimic libsecp256k1 success |
| 56 | + return 1 |
| 57 | + except ValueError: |
| 58 | + return 0 |
| 59 | + |
| 60 | + def secp256k1_ecdh(self, ctx, output, pubkey, seckey, hashfn=FFI.NULL, hasharg=FFI.NULL): |
| 61 | + try: |
| 62 | + result = usecp256k1.usecp256k1_ecdh(pubkey, seckey) |
| 63 | + if result is None: |
| 64 | + return 0 |
| 65 | + output[:32] = result |
| 66 | + return 1 |
51 | 67 | except ValueError: |
52 | | - return 0 # Handle errors like invalid signature length |
| 68 | + return 0 |
53 | 69 |
|
54 | 70 | # Instantiate ffi and lib |
55 | 71 | ffi = FFI() |
56 | 72 | lib = Lib() |
57 | 73 |
|
58 | | -# Feature flags (set based on your usecp256k1 module's capabilities) |
| 74 | +# Feature flags |
59 | 75 | HAS_RECOVERABLE = hasattr(usecp256k1, 'usecp256k1_ecdsa_sign_recoverable') |
60 | 76 | HAS_SCHNORR = hasattr(usecp256k1, 'usecp256k1_schnorrsig_sign') |
61 | 77 | HAS_ECDH = hasattr(usecp256k1, 'usecp256k1_ecdh') |
62 | 78 | HAS_EXTRAKEYS = hasattr(usecp256k1, 'usecp256k1_keypair_create') |
| 79 | + |
| 80 | +# Define copy_x for ECDH |
| 81 | +def copy_x(output, x32, y32, data): |
| 82 | + ffi.memmove(output, x32, 32) |
| 83 | + return 1 |
0 commit comments