#include "ethjet.h" #include "tinykeccak.h" #include #include #include #include struct ethjet_context * ethjet_init () { struct ethjet_context *ctx; ctx = malloc (sizeof *ctx); if (!ctx) return NULL; ctx->ec = secp256k1_context_create (SECP256K1_CONTEXT_VERIFY); return ctx; } void ethjet_free (struct ethjet_context *ctx) { secp256k1_context_destroy (ctx->ec); free (ctx); } /* * The example contract at 0xdeadbeef just reverses its input. */ int ethjet_example (struct ethjet_context *ctx, uint8_t *in, size_t in_size, uint8_t *out, size_t out_size) { if (out_size != in_size) return 0; for (int i = 0; i < in_size; i++) out[i] = in[in_size - i - 1]; return 1; } int ethjet_ecrecover (secp256k1_context *ctx, uint8_t *in, size_t in_size, uint8_t *out, size_t out_size) { /* Input: H V R S, all 32 bytes. */ secp256k1_pubkey pubkey; secp256k1_ecdsa_recoverable_signature rsig; uint8_t *input64; uint8_t pubkey_hex[65]; size_t hexlen = 65; int recid; if (in_size != 128) return 0; if (out_size != 32) return 0; input64 = in + 64; recid = in[63] - 27; if (recid < 0 || recid > 3) return 0; if (!secp256k1_ecdsa_recoverable_signature_parse_compact (ctx, &rsig, input64, recid)) return 0; if (!secp256k1_ecdsa_recover (ctx, &pubkey, &rsig, in)) return 0; if (!secp256k1_ec_pubkey_serialize (ctx, pubkey_hex, &hexlen, &pubkey, SECP256K1_EC_UNCOMPRESSED)) return 0; if (sha3_256 (out, 32, pubkey_hex + 1, 64)) return 0; memset (out, 0, 12); return 1; } int ethjet (struct ethjet_context *ctx, enum ethjet_operation op, uint8_t *in, size_t in_size, uint8_t *out, size_t out_size) { switch (op) { case ETHJET_ECRECOVER: return ethjet_ecrecover (ctx->ec, in, in_size, out, out_size); break; case ETHJET_EXAMPLE: return ethjet_example (ctx, in, in_size, out, out_size); default: return 0; } }