diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b3f405db51..1a733421ab 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3123,7 +3123,7 @@ static secp256k1_context *secp256k1_ctx; class CSecp256k1Init { public: CSecp256k1Init() { - secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); } ~CSecp256k1Init() { secp256k1_context_destroy(secp256k1_ctx); @@ -3170,12 +3170,29 @@ CScriptID calculate_contract(const CScript& federationRedeemScript, const CBitco size_t pub_len = 33; unsigned char *pub_start = &(*(sdpc - pub_len)); CHMAC_SHA256(pub_start, pub_len).Write(fullcontract, 40).Finalize(tweak); - secp256k1_pubkey pubkey; - assert(secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey, pub_start, pub_len) == 1); + secp256k1_pubkey watchman; + secp256k1_pubkey tweaked; + assert(secp256k1_ec_pubkey_parse(secp256k1_ctx, &watchman, pub_start, pub_len) == 1); + assert(secp256k1_ec_pubkey_parse(secp256k1_ctx, &tweaked, pub_start, pub_len) == 1); // If someone creates a tweak that makes this fail, they broke SHA256 - assert(secp256k1_ec_pubkey_tweak_add(secp256k1_ctx, &pubkey, tweak) == 1); - assert(secp256k1_ec_pubkey_serialize(secp256k1_ctx, pub_start, &pub_len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + assert(secp256k1_ec_pubkey_tweak_add(secp256k1_ctx, &tweaked, tweak) == 1); + assert(secp256k1_ec_pubkey_serialize(secp256k1_ctx, pub_start, &pub_len, &tweaked, SECP256K1_EC_COMPRESSED) == 1); assert(pub_len == 33); + + // Sanity checks to reduce pegin risk. If the tweaked + // value flips a bit, we may lose pegin funds irretrievably. + // We take the tweak, derive its pubkey and check that + // `tweaked - watchman = tweak` to check the computation + // two different ways + secp256k1_pubkey tweaked2; + assert(secp256k1_ec_pubkey_create(secp256k1_ctx, &tweaked2, tweak)); + assert(secp256k1_ec_pubkey_negate(secp256k1_ctx, &watchman)); + secp256k1_pubkey* pubkey_combined[2]; + pubkey_combined[0] = &watchman; + pubkey_combined[1] = &tweaked; + secp256k1_pubkey maybe_tweaked2; + assert(secp256k1_ec_pubkey_combine(secp256k1_ctx, &maybe_tweaked2, pubkey_combined, 2)); + assert(!memcmp(&maybe_tweaked2, &tweaked2, 64)); } } }