| 643 | } |
| 644 | |
| 645 | bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, int nHashType, const uint256& hash_genesis_block, std::map<int, bilingual_str>& input_errors) |
| 646 | { |
| 647 | bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE); |
| 648 | |
| 649 | // Use CTransaction for the constant parts of the |
| 650 | // transaction to avoid rehashing. |
| 651 | const CTransaction txConst(mtx); |
| 652 | |
| 653 | PrecomputedTransactionData txdata{hash_genesis_block}; |
| 654 | std::vector<CTxOut> spent_outputs; |
| 655 | for (unsigned int i = 0; i < mtx.vin.size(); ++i) { |
| 656 | CTxIn& txin = mtx.vin[i]; |
| 657 | auto coin = coins.find(txin.prevout); |
| 658 | if (coin == coins.end() || coin->second.IsSpent()) { |
| 659 | txdata.Init(txConst, /* spent_outputs */ {}, /* force */ true); |
| 660 | break; |
| 661 | } else { |
| 662 | spent_outputs.emplace_back(coin->second.out.nAsset, coin->second.out.nValue, coin->second.out.scriptPubKey); |
| 663 | } |
| 664 | } |
| 665 | if (spent_outputs.size() == mtx.vin.size()) { |
| 666 | txdata.Init(txConst, std::move(spent_outputs), true); |
| 667 | } |
| 668 | |
| 669 | // Sign what we can, including pegin inputs: |
| 670 | mtx.witness.vtxinwit.resize(mtx.vin.size()); |
| 671 | for (unsigned int i = 0; i < mtx.vin.size(); ++i) { |
| 672 | CTxIn& txin = mtx.vin[i]; |
| 673 | const CTxInWitness& inWitness = mtx.witness.vtxinwit[i]; |
| 674 | |
| 675 | CTxOut prevTxOut; |
| 676 | if (txin.m_is_pegin) { |
| 677 | prevTxOut = GetPeginOutputFromWitness(mtx.witness.vtxinwit[i].m_pegin_witness); |
| 678 | } else { |
| 679 | auto coin = coins.find(txin.prevout); |
| 680 | if (coin == coins.end() || coin->second.IsSpent()) { |
| 681 | input_errors[i] = _("Input not found or already spent"); |
| 682 | continue; |
| 683 | } |
| 684 | prevTxOut = coin->second.out; |
| 685 | } |
| 686 | |
| 687 | const CScript& prevPubKey = prevTxOut.scriptPubKey; |
| 688 | const CConfidentialValue& amount = prevTxOut.nValue; |
| 689 | |
| 690 | SignatureData sigdata = DataFromTransaction(mtx, i, prevTxOut); |
| 691 | // Only sign SIGHASH_SINGLE if there's a corresponding output: |
| 692 | if (!fHashSingle || (i < mtx.vout.size())) { |
| 693 | ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, &txdata, nHashType), prevPubKey, sigdata); |
| 694 | } |
| 695 | |
| 696 | UpdateTransaction(mtx, i, sigdata); // ELEMENTS: is UpdateInput in Core |
| 697 | |
| 698 | // amount must be specified for valid segwit signature |
| 699 | if (amount.IsExplicit() && amount.GetAmount() == MAX_MONEY && !mtx.witness.vtxinwit[i].scriptWitness.IsNull()) { |
| 700 | input_errors[i] = _("Missing amount"); |
| 701 | continue; |
| 702 | } |