mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-15 12:51:00 +02:00
Fix bug in calculate_contract for Liquid
This commit is contained in:
parent
77ba5eec41
commit
36a5d5d0f8
1 changed files with 59 additions and 54 deletions
113
src/pegins.cpp
113
src/pegins.cpp
|
|
@ -75,67 +75,72 @@ CScript calculate_contract(const CScript& federation_script, const CScript& scri
|
|||
std::vector<std::vector<unsigned char> > solutions;
|
||||
unsigned int required;
|
||||
std::vector<std::vector<unsigned char>> keys;
|
||||
bool is_liquidv1_watchman = MatchLiquidWatchman(federation_script);
|
||||
// Sanity check federation_script only to match 3 templates
|
||||
if (federation_script != CScript() << OP_TRUE &&
|
||||
!MatchMultisig(federation_script, required, keys) &&
|
||||
!MatchLiquidWatchman(federation_script)) {
|
||||
assert(false);
|
||||
if (!is_liquidv1_watchman &&
|
||||
federation_script != CScript() << OP_TRUE &&
|
||||
!MatchMultisig(federation_script, required, keys)) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
CScript::const_iterator sdpc = federation_script.begin();
|
||||
std::vector<unsigned char> vch;
|
||||
opcodetype opcodeTmp;
|
||||
bool liquid_op_else_found = false;
|
||||
while (federation_script.GetOp(sdpc, opcodeTmp, vch))
|
||||
{
|
||||
CScript::const_iterator sdpc = federation_script.begin();
|
||||
std::vector<unsigned char> vch;
|
||||
opcodetype opcodeTmp;
|
||||
while (federation_script.GetOp(sdpc, opcodeTmp, vch))
|
||||
// For liquid watchman template, don't tweak emergency keys
|
||||
if (is_liquidv1_watchman && opcodeTmp == OP_ELSE) {
|
||||
liquid_op_else_found = true;
|
||||
}
|
||||
|
||||
size_t pub_len = 33;
|
||||
if (vch.size() == pub_len && !liquid_op_else_found)
|
||||
{
|
||||
size_t pub_len = 33;
|
||||
if (vch.size() == pub_len)
|
||||
{
|
||||
unsigned char tweak[32];
|
||||
CHMAC_SHA256(vch.data(), pub_len).Write(scriptPubKey.data(), scriptPubKey.size()).Finalize(tweak);
|
||||
int ret;
|
||||
secp256k1_pubkey watchman;
|
||||
secp256k1_pubkey tweaked;
|
||||
ret = secp256k1_ec_pubkey_parse(secp256k1_ctx_validation, &watchman, vch.data(), pub_len);
|
||||
assert(ret == 1);
|
||||
ret = secp256k1_ec_pubkey_parse(secp256k1_ctx_validation, &tweaked, vch.data(), pub_len);
|
||||
assert(ret == 1);
|
||||
// If someone creates a tweak that makes this fail, they broke SHA256
|
||||
ret = secp256k1_ec_pubkey_tweak_add(secp256k1_ctx_validation, &tweaked, tweak);
|
||||
assert(ret == 1);
|
||||
unsigned char new_pub[33];
|
||||
ret = secp256k1_ec_pubkey_serialize(secp256k1_ctx_validation, new_pub, &pub_len, &tweaked, SECP256K1_EC_COMPRESSED);
|
||||
assert(ret == 1);
|
||||
assert(pub_len == 33);
|
||||
unsigned char tweak[32];
|
||||
CHMAC_SHA256(vch.data(), pub_len).Write(scriptPubKey.data(), scriptPubKey.size()).Finalize(tweak);
|
||||
int ret;
|
||||
secp256k1_pubkey watchman;
|
||||
secp256k1_pubkey tweaked;
|
||||
ret = secp256k1_ec_pubkey_parse(secp256k1_ctx_validation, &watchman, vch.data(), pub_len);
|
||||
assert(ret == 1);
|
||||
ret = secp256k1_ec_pubkey_parse(secp256k1_ctx_validation, &tweaked, vch.data(), pub_len);
|
||||
assert(ret == 1);
|
||||
// If someone creates a tweak that makes this fail, they broke SHA256
|
||||
ret = secp256k1_ec_pubkey_tweak_add(secp256k1_ctx_validation, &tweaked, tweak);
|
||||
assert(ret == 1);
|
||||
unsigned char new_pub[33];
|
||||
ret = secp256k1_ec_pubkey_serialize(secp256k1_ctx_validation, new_pub, &pub_len, &tweaked, SECP256K1_EC_COMPRESSED);
|
||||
assert(ret == 1);
|
||||
assert(pub_len == 33);
|
||||
|
||||
// push tweaked pubkey
|
||||
std::vector<unsigned char> pub_vec(new_pub, new_pub + pub_len);
|
||||
scriptDestination << pub_vec;
|
||||
// push tweaked pubkey
|
||||
std::vector<unsigned char> pub_vec(new_pub, new_pub + pub_len);
|
||||
scriptDestination << pub_vec;
|
||||
|
||||
// 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;
|
||||
ret = secp256k1_ec_pubkey_create(secp256k1_ctx_validation, &tweaked2, tweak);
|
||||
assert(ret);
|
||||
ret = secp256k1_ec_pubkey_negate(secp256k1_ctx_validation, &watchman);
|
||||
assert(ret);
|
||||
secp256k1_pubkey* pubkey_combined[2];
|
||||
pubkey_combined[0] = &watchman;
|
||||
pubkey_combined[1] = &tweaked;
|
||||
secp256k1_pubkey maybe_tweaked2;
|
||||
ret = secp256k1_ec_pubkey_combine(secp256k1_ctx_validation, &maybe_tweaked2, pubkey_combined, 2);
|
||||
assert(ret);
|
||||
assert(!memcmp(&maybe_tweaked2, &tweaked2, 64));
|
||||
// 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;
|
||||
ret = secp256k1_ec_pubkey_create(secp256k1_ctx_validation, &tweaked2, tweak);
|
||||
assert(ret);
|
||||
ret = secp256k1_ec_pubkey_negate(secp256k1_ctx_validation, &watchman);
|
||||
assert(ret);
|
||||
secp256k1_pubkey* pubkey_combined[2];
|
||||
pubkey_combined[0] = &watchman;
|
||||
pubkey_combined[1] = &tweaked;
|
||||
secp256k1_pubkey maybe_tweaked2;
|
||||
ret = secp256k1_ec_pubkey_combine(secp256k1_ctx_validation, &maybe_tweaked2, pubkey_combined, 2);
|
||||
assert(ret);
|
||||
assert(!memcmp(&maybe_tweaked2, &tweaked2, 64));
|
||||
} else {
|
||||
// add to script untouched
|
||||
if (vch.size() > 0) {
|
||||
scriptDestination << vch;
|
||||
} else {
|
||||
// add to script untouched
|
||||
if (vch.size() > 0) {
|
||||
scriptDestination << vch;
|
||||
} else {
|
||||
scriptDestination << opcodeTmp;
|
||||
}
|
||||
scriptDestination << opcodeTmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -441,5 +446,5 @@ bool MatchLiquidWatchman(const CScript& script)
|
|||
return false;
|
||||
}
|
||||
// No more pushes
|
||||
return (it + 1 == script.end());
|
||||
return (it == script.end());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue