mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +02:00
pset: verify blind value and asset proofs when signing
This commit is contained in:
parent
a7ef9f325d
commit
b2a7007961
5 changed files with 56 additions and 2 deletions
|
|
@ -64,6 +64,21 @@ bool CreateAssetSurjectionProof(std::vector<unsigned char>& output_proof, const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool VerifyBlindAssetProof(const std::vector<unsigned char>& proof, const CConfidentialAsset& conf_asset)
|
||||
{
|
||||
secp256k1_surjectionproof surj_proof;
|
||||
if (secp256k1_surjectionproof_parse(secp256k1_blind_context, &surj_proof, proof.data(), proof.size()) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
secp256k1_generator gen;
|
||||
if (secp256k1_generator_parse(secp256k1_blind_context, &gen, conf_asset.vchCommitment.data()) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return secp256k1_surjectionproof_verify(secp256k1_blind_context, &surj_proof, &gen, 1, &gen) == 0;
|
||||
}
|
||||
|
||||
uint256 GenerateRangeproofECDHKey(CPubKey& ephemeral_pubkey, const CPubKey blinding_pubkey)
|
||||
{
|
||||
// Generate ephemeral key for ECDH nonce generation
|
||||
|
|
@ -115,6 +130,26 @@ bool CreateBlindValueProof(std::vector<unsigned char>& rangeproof, const uint256
|
|||
return res == 1;
|
||||
}
|
||||
|
||||
bool VerifyBlindValueProof(CAmount value, const CConfidentialValue& conf_value, const std::vector<unsigned char>& proof, const CConfidentialAsset& conf_asset)
|
||||
{
|
||||
secp256k1_pedersen_commitment value_commit;
|
||||
if (secp256k1_pedersen_commitment_parse(secp256k1_blind_context, &value_commit, conf_value.vchCommitment.data()) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
secp256k1_generator gen;
|
||||
if (secp256k1_generator_parse(secp256k1_blind_context, &gen, conf_asset.vchCommitment.data()) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t min_value;
|
||||
uint64_t max_value;
|
||||
if (secp256k1_rangeproof_verify(secp256k1_blind_context, &min_value, &max_value, &value_commit, proof.data(), proof.size(), /* extra_commit */ nullptr, /* extra_commit_len */ 0, &gen) == 0) {
|
||||
return false;
|
||||
}
|
||||
return min_value == (uint64_t)value;
|
||||
}
|
||||
|
||||
void CreateAssetCommitment(CConfidentialAsset& conf_asset, secp256k1_generator& asset_gen, const CAsset& asset, const uint256& asset_blinder)
|
||||
{
|
||||
conf_asset.vchCommitment.resize(CConfidentialAsset::nCommittedSize);
|
||||
|
|
|
|||
|
|
@ -31,9 +31,11 @@ enum class BlindingStatus
|
|||
std::string GetBlindingStatusError(const BlindingStatus& status);
|
||||
|
||||
bool CreateAssetSurjectionProof(std::vector<unsigned char>& output_proof, const std::vector<secp256k1_fixed_asset_tag>& fixed_input_tags, const std::vector<secp256k1_generator>& ephemeral_input_tags, const std::vector<uint256>& input_asset_blinders, const uint256& output_asset_blinder, const secp256k1_generator& output_asset_tag, const CAsset& asset, size_t num_targets = MAX_SURJECTION_TARGETS);
|
||||
bool VerifyBlindAssetProof(const std::vector<unsigned char>& proof, const CConfidentialAsset& conf_asset);
|
||||
uint256 GenerateRangeproofECDHKey(CPubKey& ephemeral_pubkey, const CPubKey blinding_pubkey);
|
||||
bool CreateValueRangeProof(std::vector<unsigned char>& rangeproof, const uint256& value_blinder, const uint256& nonce, const CAmount amount, const CScript& scriptPubKey, const secp256k1_pedersen_commitment& value_commit, const secp256k1_generator& gen, const CAsset& asset, const uint256& asset_blinder);
|
||||
bool CreateBlindValueProof(std::vector<unsigned char>& rangeproof, const uint256& value_blinder, const CAmount amount, const secp256k1_pedersen_commitment& value_commit, const secp256k1_generator& gen);
|
||||
bool VerifyBlindValueProof(CAmount value, const CConfidentialValue& conf_value, const std::vector<unsigned char>& proof, const CConfidentialAsset& conf_asset);
|
||||
void CreateAssetCommitment(CConfidentialAsset& conf_asset, secp256k1_generator& asset_gen, const CAsset& asset, const uint256& asset_blinder);
|
||||
void CreateValueCommitment(CConfidentialValue& conf_value, secp256k1_pedersen_commitment& value_commit, const uint256& value_blinder, const secp256k1_generator& asset_gen, const CAmount amount);
|
||||
BlindingStatus BlindPSBT(PartiallySignedTransaction& psbt, std::map<uint32_t, std::tuple<CAmount, CAsset, uint256, uint256>> our_input_data, std::map<uint32_t, std::pair<CKey, CKey>> our_issuances_to_blind);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ bilingual_str TransactionErrorString(const TransactionError err)
|
|||
return Untranslated("Transaction values or blinders are not balanced");
|
||||
case TransactionError::UTXOS_MISSING_BALANCE_CHECK:
|
||||
return Untranslated("Missing UTXOs that are needed to check transaction balance");
|
||||
case TransactionError::INVALID_VALUE_PROOF:
|
||||
return Untranslated("Proof of blinded value is invalid");
|
||||
case TransactionError::INVALID_ASSET_PROOF:
|
||||
return Untranslated("Proof of blinded asset is invalid");
|
||||
// no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
assert(false);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ enum class TransactionError {
|
|||
BLINDING_REQUIRED,
|
||||
VALUE_IMBALANCE,
|
||||
UTXOS_MISSING_BALANCE_CHECK,
|
||||
INVALID_VALUE_PROOF,
|
||||
INVALID_ASSET_PROOF,
|
||||
};
|
||||
|
||||
bilingual_str TransactionErrorString(const TransactionError error);
|
||||
|
|
|
|||
|
|
@ -2830,10 +2830,21 @@ BlindingStatus CWallet::WalletBlindPSBT(PartiallySignedTransaction& psbtx) const
|
|||
TransactionError CWallet::SignPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool imbalance_ok, bool bip32derivs, size_t* n_signed) const
|
||||
{
|
||||
// If we're signing, check that the transaction is not still in need of blinding
|
||||
// Also check that the amount and asset proofs are valid
|
||||
if (sign) {
|
||||
for (const PSBTOutput& o : psbtx.outputs) {
|
||||
if (o.IsBlinded() && !o.IsFullyBlinded()) {
|
||||
return TransactionError::BLINDING_REQUIRED;
|
||||
if (o.IsBlinded()) {
|
||||
if (!o.IsFullyBlinded()) {
|
||||
return TransactionError::BLINDING_REQUIRED;
|
||||
}
|
||||
assert(!o.m_blind_value_proof.empty());
|
||||
assert(!o.m_blind_asset_proof.empty());
|
||||
if (!VerifyBlindValueProof(*o.amount, o.m_value_commitment, o.m_blind_value_proof, o.m_asset_commitment)) {
|
||||
return TransactionError::INVALID_VALUE_PROOF;
|
||||
}
|
||||
if (!VerifyBlindAssetProof(o.m_blind_asset_proof, o.m_asset_commitment)) {
|
||||
return TransactionError::INVALID_ASSET_PROOF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue