mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +02:00
Enable analyzepsbt
This commit is contained in:
parent
b65a00f095
commit
64b30bfc3d
7 changed files with 92 additions and 88 deletions
|
|
@ -17,12 +17,9 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
|||
// Go through each input and build status
|
||||
PSBTAnalysis result;
|
||||
|
||||
result.SetInvalid("Disabled");
|
||||
return result;
|
||||
|
||||
/*
|
||||
bool calc_fee = true;
|
||||
CAmountMap in_amts;
|
||||
// Elements things
|
||||
bool needs_blinded_outputs = false;
|
||||
bool has_blinded_outputs = false;
|
||||
|
||||
result.inputs.resize(psbtx.inputs.size());
|
||||
|
||||
|
|
@ -36,22 +33,23 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
|||
// Check for a UTXO
|
||||
CTxOut utxo;
|
||||
if (input.GetUTXO(utxo)) {
|
||||
//TODO(gwillen) do PSBT inputs always have explicit assets & amounts?
|
||||
if (!MoneyRange(utxo.nValue.GetAmount()) || !MoneyRange(in_amts[utxo.nAsset.GetAsset()] + utxo.nValue.GetAmount())) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Input %u has invalid value", i));
|
||||
return result;
|
||||
if (utxo.nValue.IsExplicit()) {
|
||||
if (!MoneyRange(utxo.nValue.GetAmount())) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Input %u has invalid value", i));
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
needs_blinded_outputs = true;
|
||||
}
|
||||
in_amts[utxo.nAsset.GetAsset()] += utxo.nValue.GetAmount();
|
||||
input_analysis.has_utxo = true;
|
||||
} else {
|
||||
if (input.non_witness_utxo && input.prev_out >= input.non_witness_utxo->vout.size()) {
|
||||
if (input.non_witness_utxo && *input.prev_out >= input.non_witness_utxo->vout.size()) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Input %u specifies invalid prevout", i));
|
||||
return result;
|
||||
}
|
||||
input_analysis.has_utxo = false;
|
||||
input_analysis.is_final = false;
|
||||
input_analysis.next = PSBTRole::UPDATER;
|
||||
calc_fee = false;
|
||||
}
|
||||
|
||||
if (!utxo.IsNull() && utxo.scriptPubKey.IsUnspendable()) {
|
||||
|
|
@ -88,6 +86,69 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
|||
}
|
||||
}
|
||||
|
||||
for (const PSBTOutput& output : psbtx.outputs) {
|
||||
CTxOut txout = output.GetTxOut();
|
||||
if (output.IsBlinded()) {
|
||||
has_blinded_outputs = true;
|
||||
if (!output.IsFullyBlinded()) {
|
||||
result.next = PSBTRole::BLINDER;
|
||||
}
|
||||
} else {
|
||||
// Find the fee output
|
||||
if (txout.IsFee()) {
|
||||
if (result.fee != nullopt) {
|
||||
result.SetInvalid("There is more than one fee output");
|
||||
return result;
|
||||
}
|
||||
result.fee = output.amount;
|
||||
}
|
||||
}
|
||||
if (txout.nValue.IsExplicit() && !MoneyRange(txout.nValue.GetAmount())) {
|
||||
result.SetInvalid("PSBT is not valid. Output amount invalid");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.fee == nullopt) {
|
||||
result.SetInvalid("PSBT missing required fee output");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (needs_blinded_outputs && !has_blinded_outputs) {
|
||||
result.SetInvalid("PSBT has blinded inputs but no blinded outputs. Must have at least one blinded output to balance with the inputs");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Estimate the size
|
||||
CMutableTransaction mtx(psbtx.GetUnsignedTx());
|
||||
CCoinsView view_dummy;
|
||||
CCoinsViewCache view(&view_dummy);
|
||||
bool success = true;
|
||||
|
||||
for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
|
||||
PSBTInput& input = psbtx.inputs[i];
|
||||
Coin newcoin;
|
||||
|
||||
if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, nullptr, true) || !input.GetUTXO(newcoin.out)) {
|
||||
success = false;
|
||||
break;
|
||||
} else {
|
||||
mtx.vin[i].scriptSig = input.final_script_sig;
|
||||
mtx.witness.vtxinwit[i].scriptWitness = input.final_script_witness;
|
||||
newcoin.nHeight = 1;
|
||||
view.AddCoin(input.GetOutPoint(), std::move(newcoin), true);
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
CTransaction ctx = CTransaction(mtx);
|
||||
size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
|
||||
result.estimated_vsize = size;
|
||||
// Estimate fee rate
|
||||
CFeeRate feerate(*result.fee, size);
|
||||
result.estimated_feerate = feerate;
|
||||
}
|
||||
|
||||
// Calculate next role for PSBT by grabbing "minimum" PSBTInput next role
|
||||
result.next = PSBTRole::EXTRACTOR;
|
||||
for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
|
||||
|
|
@ -96,64 +157,6 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
|||
}
|
||||
assert(result.next > PSBTRole::CREATOR);
|
||||
|
||||
if (calc_fee) {
|
||||
// Get the output amount
|
||||
CAmountMap out_amts = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmountMap(),
|
||||
[](CAmountMap a, const CTxOut& b) {
|
||||
CAmount acc = a[b.nAsset.GetAsset()];
|
||||
CAmount add = b.nValue.GetAmount();
|
||||
|
||||
if (!MoneyRange(acc) || !MoneyRange(add) || !MoneyRange(acc + add)) {
|
||||
CAmountMap invalid;
|
||||
invalid[::policyAsset] = CAmount(-1);
|
||||
return invalid;
|
||||
}
|
||||
a[b.nAsset.GetAsset()] += add;
|
||||
return a;
|
||||
}
|
||||
);
|
||||
if (!MoneyRange(out_amts)) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Output amount invalid"));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get the fee
|
||||
CAmountMap fee = in_amts - out_amts;
|
||||
result.fee = fee;
|
||||
|
||||
// Estimate the size
|
||||
CMutableTransaction mtx(psbtx.GetUnsignedTx());
|
||||
CCoinsView view_dummy;
|
||||
CCoinsViewCache view(&view_dummy);
|
||||
bool success = true;
|
||||
|
||||
for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
|
||||
PSBTInput& input = psbtx.inputs[i];
|
||||
Coin newcoin;
|
||||
|
||||
if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, nullptr, true) || !input.GetUTXO(newcoin.out)) {
|
||||
success = false;
|
||||
break;
|
||||
} else {
|
||||
mtx.vin[i].scriptSig = input.final_script_sig;
|
||||
mtx.witness.vtxinwit[i].scriptWitness = input.final_script_witness;
|
||||
newcoin.nHeight = 1;
|
||||
view.AddCoin(input.GetOutPoint(), std::move(newcoin), true);
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
CTransaction ctx = CTransaction(mtx);
|
||||
size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
|
||||
result.estimated_vsize = size;
|
||||
// Estimate fee rate
|
||||
CFeeRate feerate(fee[::policyAsset], size);
|
||||
result.estimated_feerate = feerate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue