fix(p2pk): validate expected pubkey correctly for p2pk inputs#2408
fix(p2pk): validate expected pubkey correctly for p2pk inputs#2408
Conversation
and integrate it in check_all_utxo_inputs_signed_by_pub
specifically, don't require coin. this makes it easier to test also add a fixme regarding pubkey size in the scriptpub, it might be: - OP_PUSHBYTES_33 33-byte-compressed-pubkey OP_CHECKSIG - OP_PUSHBYTES_65 65-byte-full-pubkey OP_CHECKSIG
and change the parameters of the func for now to allow for uncompressed pubkeys since i can't find any compressed pubkey transactions online that i can use for testing
also add a fixme for a bug found with this impl for overwintered transactions: those transactions need to have the amount field set, which generally isn't set because it is fetched from UtxoTx object which doesn't have the amount set as well.
found in scriptPub. i.e. we will assume the public key in scriptpub was compressed and try to verify the signature, if we fail, we will assume it's uncompressed and try to verify the signature again. if either of these two operations succeed, verification succeeds, if both fail, verification fails.
95d86db to
d1b2e4e
Compare
|
force pushed to move out unrelated commits away to #2410 |
mm2src/coins/utxo/utxo_common.rs
Outdated
| // FIXME: For overwintered txs, we also need to set the input amount as it's used in sighash calcuations! | ||
| unsigned_tx.consensus_branch_id = coin.as_ref().conf.consensus_branch_id; |
There was a problem hiding this comment.
to fix this, we need to query for the amount of this input. so one rpc request per p2pk input.
i think the efficient solution for this is to disable this check all together for p2pk spends on overwintered txs.
There was a problem hiding this comment.
I think you may just query the previous scriptPubKey for p2pk inputs.
This would be a one for all solution as you would not need to check the signature but just retrieve the pubkey from the previous scriptPubKey
There was a problem hiding this comment.
that's the same communication overhead, but i think is a neater solution.
we wouldn't wanna perform it though if the transaction/coin isn't overwintered, because we already have all the info needed to verify the taker is the owner of the utxos without the need for a network request.
There was a problem hiding this comment.
we wouldn't wanna perform it though if the transaction/coin isn't overwintered, because we already have all the info needed to verify the taker is the owner of the utxos without the need for a network request.
I prefer to not use a network request when it's not needed.
mm2src/coins/utxo/utxo_common.rs
Outdated
| let mut unsigned_tx: TransactionInputSigner = tx.clone().into(); | ||
| // FIXME: For overwintered txs, we also need to set the input amount as it's used in sighash calcuations! | ||
| unsigned_tx.consensus_branch_id = coin.as_ref().conf.consensus_branch_id; |
There was a problem hiding this comment.
Would it also be okay to modify the original tx's consensus_branch_id
There was a problem hiding this comment.
this field doesn't get set when we get the TransactionInputSigner from a plain Transaction (check https://github.com/KomodoPlatform/komodo-defi-framework/blob/a97afb467eaf24fe6530f3f7341d7173a3777c41/mm2src/mm2_bitcoin/script/src/sign.rs#L177).
it must be this one of the coin anyways and matches with the one used by the taker. otherwise all the transaction signing will break and not verify.
i will might remove such mutation anyway as consensus_branch_id is only used with overwintered txs, and we already have a problem with them with them: namely, the amount must be set for signing to produce correct signature.
rust-analyzer's auto import did that ;p
mm2src/coins/utxo/utxo_common.rs
Outdated
| &pubkey_script, | ||
| // FIXME: But P2PK scripts never use segwit as signature version. Should we hardcode this to SignatureVersion::Base or ::ForkId? | ||
| // UPD: I think we can safely remove this fixme if the following reasoning holds: | ||
| // Since we are using p2pk here, this means the coin isn't segwit. right? but it's the coin supplied from the caller anyways |
There was a problem hiding this comment.
I think, KDF does not mix segwit and non segwit inputs but another app could.
(here we actually check txns created by a remote app)
There was a problem hiding this comment.
upon digging down, looks like we list p2pk utxos for segwit address:
https://github.com/KomodoPlatform/komodo-defi-framework/blob/b161cd44aff8ea5f140018c2589ee90d00952454/mm2src/coins/utxo/rpc_clients/electrum_rpc/client.rs#L805-L809
we should check address.address_format.is_segwit() and not add p2pk outputs if so. i.e. we should associate p2pk outputs only with coins enabled in non-segwit mode, i.e. coins enabled for p2pkh outputs.
another alternative is to change signature_version passed to signature_hash_to_sign for each input based on its utxo type (p.s. actually this will look inconsistent; raising the question why is a coin labeled as segwit but it can spend other address types)
There was a problem hiding this comment.
we should check address.address_format.is_segwit() and not add p2pk outputs
maybe just do not allow to add a pubkey to segwit addr
|
@mariocynicys please merge with latest dev for wasm tests job to pass. |
…e expected pubkey this simplifies things a lot as no verification is now needed. the down side is that we now query the rpc for each and every p2pk input and not just overwintered ones. this is prolly OK tho since p2pk inputs aren't that popular anyways. ofc we assume the rpc server isn't lying
|
the latest commit applies this suggestion #2408 (comment) the one before applies the amount fetching + sig verification suggestion. im fine with either one of them (or removing the check for overwintered p2pk all together also). |
…ainst the expected pubkey" This reverts commit 8fdd7d3. we will stick with only performing the network request when needed (so only for overwintered)
as there is no need for the verbose transaction
that's either a coinbase tx or an invalid tx with no inputs (most probably the latter). if it's invalid, we don't really care about that within the scope of this function
since it won't be needed most of the time as it's only used when an input is p2pk
… empty" This reverts commit a2c8f8f.
* dev: (29 commits) fix(p2pk): validate expected pubkey correctly for p2pk inputs (#2408) chore(docs): update old urls referencing atomicdex or old docs pages (#2428) improvement(p2p): remove hardcoded seeds (#2439) fix(evm-api): find enabled erc20 token using platform ticker (#2445) chore(docs): add DeepWiki badge to README (#2463) chore(core): organize deps using workspace.dependencies (#2449) feat(db-arch): more dbdir to address_dir replacements (#2398) chore(build-artifacts): remove duplicated mm2 build artifacts (#2448) feat(pubkey-banning): expirable bans (#2455) fix(eth-balance-events): serialize eth address using AddrToString (#2440) chore(deps): remove base58 and replace it completely with bs58 (#2427) feat(tron): initial groundwork for full TRON integration (#2425) fix(UTXO): improve tx fee calculation and min relay fee handling (#2316) deps(timed-map): bump to 1.3.1 (#2413) improvement(tendermint): safer IBC channel handler (#2298) chore(release): complete v2.4.0-beta changelogs (#2436) fix(event-streaming): initial addresses registration in utxo balance streaming (#2431) improvement(watchers): re-write use-watchers handling (#2430) fix(evm): make withdraw_nft work in HD mode (#2424) feat(taproot): support parsing taproot output address types ...
* lr-swap-wip: (37 commits) fix custom token error name fix getting chain_id from protocol_data refactor (review): use dedicated large error cfg, add new fn to FromApiValueError, fix TODO, use experimental namespace for lr rpc, more Ticker alias feat(walletconnect): add WalletConnect v2 support for EVM and Cosmos (GLEECBTC#2223) feat(ibc-routing-part-1): supporting entire Cosmos network for swaps (GLEECBTC#2459) fix(test): fix HD Wallet message signing tests (GLEECBTC#2474) improvement(builds): enable static CRT linking for MSVC builds (GLEECBTC#2464) feat(wallet): implement HD multi-address support for message signing (GLEECBTC#2432) fix(p2pk): validate expected pubkey correctly for p2pk inputs (GLEECBTC#2408) chore(docs): update old urls referencing atomicdex or old docs pages (GLEECBTC#2428) improvement(p2p): remove hardcoded seeds (GLEECBTC#2439) fix(evm-api): find enabled erc20 token using platform ticker (GLEECBTC#2445) chore(docs): add DeepWiki badge to README (GLEECBTC#2463) chore(core): organize deps using workspace.dependencies (GLEECBTC#2449) feat(db-arch): more dbdir to address_dir replacements (GLEECBTC#2398) chore(build-artifacts): remove duplicated mm2 build artifacts (GLEECBTC#2448) feat(pubkey-banning): expirable bans (GLEECBTC#2455) fix(eth-balance-events): serialize eth address using AddrToString (GLEECBTC#2440) chore(deps): remove base58 and replace it completely with bs58 (GLEECBTC#2427) feat(tron): initial groundwork for full TRON integration (GLEECBTC#2425) ...
For p2pk inputs, the pubkey isn't included in the scriptSig. The scriptSig only includes the signature and that's it.
This means we can't just read the pubkey from the scriptSig and deduce that such pubkey is the owner of the utxo (and then compare it with the expected pubkey, taker or maker). But rather we need to verify the signature in the scriptSig using the expected pubkey.
ref. https://learnmeabitcoin.com/technical/script/p2pk/
Fixes #2339