Search code examples
c++ethereumsignatureecdsa

Howto calculate v (parity / recovery Id) for ECDSA signature using secp256k1 library in C++?


I use the following code (secp256k1 lib for linux) to create an ethereum tx signature in C++:

secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);

int res = secp256k1_ec_seckey_verify(ctx, secret);
if(!res)
{
    secp256k1_context_destroy(ctx);
    return false;
}

secp256k1_ecdsa_signature sig;
res = secp256k1_ecdsa_sign(ctx, &sig, (uint8_t*) hash.data(), secret, NULL/*secp256k1_nonce_function_rfc6979*/, NULL);
if(!res)
{
    secp256k1_context_destroy(ctx);
    return false;
}

unsigned char buf[64];
secp256k1_ecdsa_signature_serialize_compact(ctx, buf, &sig);

char r[65], s[65];
r = byteArrayToCharArray(r, buf, 32);
s = byteArrayToCharArray(s, buf + 32, 32);
// v = ???

My problem is that I don't know how to calculate v using this library. Can anybody give me a hint?


Solution

  • Here is the life-saving code for everyone reads it afterward:

    secp256k1_ecdsa_recoverable_signature rawSig;
    int res = secp256k1_ecdsa_sign_recoverable(ctx, &rawSig, (uint8_t*) hash.data(), secret, NULL/*secp256k1_nonce_function_rfc6979*/, NULL);
    if(!res)
    {
        secp256k1_context_destroy(ctx);
        return false;
    }
    
    Signature sig;
    v = 0;
    secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig.data(), &v, &rawSig);
    SignatureStruct& ss = *reinterpret_cast<SignatureStruct*>(&sig);
    ss.v = static_cast<byte>(v);
    if (ss.s > c_secp256k1n / 2)
    {
        ss.v = static_cast<byte>(ss.v ^ 1);
        ss.s = h256(c_secp256k1n - u256(ss.s));
    }
    
    if (ss.s > c_secp256k1n / 2)
    {
        secp256k1_context_destroy(ctx);
        return false;
    }
    
    char r[65], s[65];
    r = byteArrayToCharArray(r, (uint8_t*) ss.r.data(), 32);
    s = byteArrayToCharArray(s, (uint8_t*) ss.s.data(), 32);
    v = ss.v % 2;
    

    Note that you must have already compiled secp256k1 library with the recovery module enabled or you will get a linkage error.
    I hope it helps somebody.