diff --git a/.gitignore b/.gitignore index f3f3071..c18eb1d 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,5 @@ external/libwally-core # generated doc doc/html* doc/latex + +.vscode diff --git a/src/cfddlc_transactions.cpp b/src/cfddlc_transactions.cpp index af26010..de2c44a 100644 --- a/src/cfddlc_transactions.cpp +++ b/src/cfddlc_transactions.cpp @@ -206,7 +206,7 @@ AdaptorPair DlcManager::CreateCetAdaptorSignature( std::vector DlcManager::CreateCetAdaptorSignatures( const std::vector& cets, const SchnorrPubkey& oracle_pubkey, - const std::vector& oracle_r_value, const Privkey& funding_sk, + const std::vector& oracle_r_values, const Privkey& funding_sk, const Script& funding_script_pubkey, const Amount& total_collateral, const std::vector>& msgs) { size_t nb = cets.size(); @@ -217,8 +217,12 @@ std::vector DlcManager::CreateCetAdaptorSignatures( std::vector sigs; for (size_t i = 0; i < nb; i++) { + std::vector r_values; + for (size_t j = 0; j < msgs[i].size(); j++) { + r_values.push_back(oracle_r_values[j]); + } sigs.push_back(CreateCetAdaptorSignature( - cets[i], oracle_pubkey, oracle_r_value, funding_sk, + cets[i], oracle_pubkey, r_values, funding_sk, funding_script_pubkey, total_collateral, msgs[i])); } @@ -257,9 +261,13 @@ bool DlcManager::VerifyCetAdaptorSignatures( bool all_valid = true; for (size_t i = 0; i < nb && all_valid; i++) { + std::vector r_values; + for (size_t j = 0; j < msgs[i].size(); j++) { + r_values.push_back(oracle_r_values[j]); + } all_valid &= VerifyCetAdaptorSignature( signature_and_proofs[i], cets[i], pubkey, oracle_pubkey, - oracle_r_values, funding_script_pubkey, total_collateral, msgs[i]); + r_values, funding_script_pubkey, total_collateral, msgs[i]); } return all_valid; @@ -304,7 +312,7 @@ void DlcManager::SignCet(TransactionController* cet, throw new CfdException(CfdError::kCfdIllegalArgumentError, "Public key not part of the multi sig script."); } -} +} // namespace dlc ByteData DlcManager::GetRawFundingTransactionInputSignature( const TransactionController& funding_transaction, const Privkey& privkey, diff --git a/test/test_cfddlc_transactions.cpp b/test/test_cfddlc_transactions.cpp index 2d94e14..2e74cbe 100644 --- a/test/test_cfddlc_transactions.cpp +++ b/test/test_cfddlc_transactions.cpp @@ -43,6 +43,10 @@ const std::vector WIN_MESSAGES_HASH = { HashUtil::Sha256(WIN_MESSAGES[0]), HashUtil::Sha256(WIN_MESSAGES[1])}; const std::vector LOSE_MESSAGES_HASH = { HashUtil::Sha256(LOSE_MESSAGES[0]), HashUtil::Sha256(LOSE_MESSAGES[1])}; +const std::vector WIN_MESSAGES_HASH_FEWER_MESSAGES = { + HashUtil::Sha256(WIN_MESSAGES[0])}; +const std::vector LOSE_MESSAGES_HASH_FEWER_MESSAGES = { + HashUtil::Sha256(LOSE_MESSAGES[0])}; const std::vector> MESSAGES_HASH = { WIN_MESSAGES_HASH, LOSE_MESSAGES_HASH}; const Privkey ORACLE_PRIVKEY( @@ -568,3 +572,36 @@ TEST(DlcManager, AdaptorSigMultipleNonces) { fund_amount, WitnessVersion::kVersion0); EXPECT_TRUE(is_valid); } + +TEST(DlcManager, AdaptorSigMultipleNoncesWithFewerMessagesThanNonces) { + std::vector outcomes = {{WIN_AMOUNT, LOSE_AMOUNT}, + {LOSE_AMOUNT, WIN_AMOUNT}}; + auto dlc_transactions = DlcManager::CreateDlcTransactions( + outcomes, LOCAL_PARAMS, REMOTE_PARAMS, REFUND_LOCKTIME, 1, PREMIUM_DEST, + OPTION_PREMIUM); + auto fund_transaction = dlc_transactions.fund_transaction; + auto cets = dlc_transactions.cets; + auto cet0 = cets[0]; + auto lock_script = DlcManager::CreateFundTxLockingScript(LOCAL_FUND_PUBKEY, + REMOTE_FUND_PUBKEY); + + auto fund_amount = fund_transaction.GetTransaction().GetTxOut(0).GetValue(); + auto fund_txid = fund_transaction.GetTransaction().GetTxid(); + + auto adaptor_pairs = DlcManager::CreateCetAdaptorSignatures( + cets, ORACLE_PUBKEY, ORACLE_R_POINTS, LOCAL_FUND_PRIVKEY, lock_script, + fund_amount, {WIN_MESSAGES_HASH_FEWER_MESSAGES, LOSE_MESSAGES_HASH_FEWER_MESSAGES}); + + EXPECT_TRUE(DlcManager::VerifyCetAdaptorSignature( + adaptor_pairs[1], cets[1], LOCAL_FUND_PUBKEY, ORACLE_PUBKEY, + {ORACLE_R_POINTS[0]}, lock_script, fund_amount, LOSE_MESSAGES_HASH_FEWER_MESSAGES)); + + auto adaptor_secret = ORACLE_SIGNATURES[0].GetPrivkey(); + auto adapted_sig = + AdaptorUtil::Adapt(adaptor_pairs[0].signature, adaptor_secret); + + auto is_valid = cet0.VerifyInputSignature( + adapted_sig, LOCAL_FUND_PUBKEY, fund_txid, 0, lock_script, SigHashType(), + fund_amount, WitnessVersion::kVersion0); + EXPECT_TRUE(is_valid); +}