Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/rpcwallet.cpp
Show First 20 Lines • Show All 4,574 Lines • ▼ Show 20 Lines | static UniValue sethdseed(const Config &config, const JSONRPCRequest &request) { | ||||
if (flush_key_pool) { | if (flush_key_pool) { | ||||
pwallet->NewKeyPool(); | pwallet->NewKeyPool(); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
bool FillPSBT(const CWallet *pwallet, PartiallySignedTransaction &psbtx, | bool FillPSBT(const CWallet *pwallet, PartiallySignedTransaction &psbtx, | ||||
const CTransaction *txConst, SigHashType sighash_type, bool sign, | SigHashType sighash_type, bool sign, bool bip32derivs) { | ||||
bool bip32derivs) { | |||||
LOCK(pwallet->cs_wallet); | LOCK(pwallet->cs_wallet); | ||||
// Get all of the previous transactions | // Get all of the previous transactions | ||||
bool complete = true; | bool complete = true; | ||||
for (size_t i = 0; i < txConst->vin.size(); ++i) { | for (size_t i = 0; i < psbtx.tx->vin.size(); ++i) { | ||||
const CTxIn &txin = txConst->vin[i]; | const CTxIn &txin = psbtx.tx->vin[i]; | ||||
PSBTInput &input = psbtx.inputs.at(i); | PSBTInput &input = psbtx.inputs.at(i); | ||||
// If we don't know about this input, skip it and let someone else deal | if (PSBTInputSigned(input)) { | ||||
// with it | continue; | ||||
} | |||||
// Verify input looks sane. | |||||
if (!input.IsSane()) { | |||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, | |||||
"PSBT input is not sane."); | |||||
} | |||||
// If we have no utxo, grab it from the wallet. | |||||
if (input.utxo.IsNull()) { | |||||
const TxId &txid = txin.prevout.GetTxId(); | const TxId &txid = txin.prevout.GetTxId(); | ||||
const auto it = pwallet->mapWallet.find(txid); | const auto it = pwallet->mapWallet.find(txid); | ||||
if (it != pwallet->mapWallet.end()) { | if (it != pwallet->mapWallet.end()) { | ||||
const CWalletTx &wtx = it->second; | const CWalletTx &wtx = it->second; | ||||
CTxOut utxo = wtx.tx->vout[txin.prevout.GetN()]; | CTxOut utxo = wtx.tx->vout[txin.prevout.GetN()]; | ||||
// Update UTXOs from the wallet. | // Update UTXOs from the wallet. | ||||
input.utxo = utxo; | input.utxo = utxo; | ||||
} | } | ||||
} | |||||
// Get the Sighash type | // Get the Sighash type | ||||
if (sign && input.sighash_type.getRawSigHashType() > 0 && | if (sign && input.sighash_type.getRawSigHashType() > 0 && | ||||
input.sighash_type != sighash_type) { | input.sighash_type != sighash_type) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_DESERIALIZATION_ERROR, | RPC_DESERIALIZATION_ERROR, | ||||
"Specified sighash and sighash in PSBT do not match."); | "Specified sighash and sighash in PSBT do not match."); | ||||
} | } | ||||
complete &= | complete &= | ||||
SignPSBTInput(HidingSigningProvider(pwallet, !sign, !bip32derivs), | SignPSBTInput(HidingSigningProvider(pwallet, !sign, !bip32derivs), | ||||
*psbtx.tx, input, i, sighash_type); | psbtx, i, sighash_type); | ||||
} | } | ||||
// Fill in the bip32 keypaths and redeemscripts for the outputs so that | // Fill in the bip32 keypaths and redeemscripts for the outputs so that | ||||
// hardware wallets can identify change | // hardware wallets can identify change | ||||
for (size_t i = 0; i < txConst->vout.size(); ++i) { | for (size_t i = 0; i < psbtx.tx->vout.size(); ++i) { | ||||
const CTxOut &out = txConst->vout.at(i); | const CTxOut &out = psbtx.tx->vout.at(i); | ||||
PSBTOutput &psbt_out = psbtx.outputs.at(i); | PSBTOutput &psbt_out = psbtx.outputs.at(i); | ||||
// Fill a SignatureData with output info | // Fill a SignatureData with output info | ||||
SignatureData sigdata; | SignatureData sigdata; | ||||
psbt_out.FillSignatureData(sigdata); | psbt_out.FillSignatureData(sigdata); | ||||
MutableTransactionSignatureCreator creator( | MutableTransactionSignatureCreator creator( | ||||
psbtx.tx.get_ptr(), 0, out.nValue, SigHashType().withForkId()); | psbtx.tx.get_ptr(), 0, out.nValue, SigHashType().withForkId()); | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | static UniValue walletprocesspsbt(const Config &config, | ||||
// Get the sighash type | // Get the sighash type | ||||
SigHashType nHashType = ParseSighashString(request.params[2]); | SigHashType nHashType = ParseSighashString(request.params[2]); | ||||
if (!nHashType.hasForkId()) { | if (!nHashType.hasForkId()) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Signature must use SIGHASH_FORKID"); | "Signature must use SIGHASH_FORKID"); | ||||
} | } | ||||
// Use CTransaction for the constant parts of the | |||||
// transaction to avoid rehashing. | |||||
const CTransaction txConst(*psbtx.tx); | |||||
// Fill transaction with our data and also sign | // Fill transaction with our data and also sign | ||||
bool sign = | bool sign = | ||||
request.params[1].isNull() ? true : request.params[1].get_bool(); | request.params[1].isNull() ? true : request.params[1].get_bool(); | ||||
bool bip32derivs = | bool bip32derivs = | ||||
request.params[3].isNull() ? false : request.params[3].get_bool(); | request.params[3].isNull() ? false : request.params[3].get_bool(); | ||||
bool complete = | bool complete = FillPSBT(pwallet, psbtx, nHashType, sign, bip32derivs); | ||||
FillPSBT(pwallet, psbtx, &txConst, nHashType, sign, bip32derivs); | |||||
UniValue result(UniValue::VOBJ); | UniValue result(UniValue::VOBJ); | ||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); | CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); | ||||
ssTx << psbtx; | ssTx << psbtx; | ||||
result.pushKV("psbt", EncodeBase64((uint8_t *)ssTx.data(), ssTx.size())); | result.pushKV("psbt", EncodeBase64(ssTx.str())); | ||||
result.pushKV("complete", complete); | result.pushKV("complete", complete); | ||||
return result; | return result; | ||||
} | } | ||||
static UniValue walletcreatefundedpsbt(const Config &config, | static UniValue walletcreatefundedpsbt(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); | std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); | ||||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | static UniValue walletcreatefundedpsbt(const Config &config, | ||||
Amount fee; | Amount fee; | ||||
int change_position; | int change_position; | ||||
CMutableTransaction rawTx = | CMutableTransaction rawTx = | ||||
ConstructTransaction(config.GetChainParams(), request.params[0], | ConstructTransaction(config.GetChainParams(), request.params[0], | ||||
request.params[1], request.params[2]); | request.params[1], request.params[2]); | ||||
FundTransaction(pwallet, rawTx, fee, change_position, request.params[3]); | FundTransaction(pwallet, rawTx, fee, change_position, request.params[3]); | ||||
// Make a blank psbt | // Make a blank psbt | ||||
PartiallySignedTransaction psbtx; | const CTransaction tx = CTransaction(rawTx); | ||||
psbtx.tx = rawTx; | PartiallySignedTransaction psbtx(tx); | ||||
for (size_t i = 0; i < rawTx.vin.size(); ++i) { | |||||
psbtx.inputs.push_back(PSBTInput()); | |||||
} | |||||
for (size_t i = 0; i < rawTx.vout.size(); ++i) { | |||||
psbtx.outputs.push_back(PSBTOutput()); | |||||
} | |||||
// Use CTransaction for the constant parts of the | |||||
// transaction to avoid rehashing. | |||||
const CTransaction txConst(*psbtx.tx); | |||||
// Fill transaction with out data but don't sign | // Fill transaction with out data but don't sign | ||||
bool bip32derivs = | bool bip32derivs = | ||||
request.params[4].isNull() ? false : request.params[4].get_bool(); | request.params[4].isNull() ? false : request.params[4].get_bool(); | ||||
FillPSBT(pwallet, psbtx, &txConst, SigHashType().withForkId(), false, | FillPSBT(pwallet, psbtx, SigHashType().withForkId(), false, bip32derivs); | ||||
bip32derivs); | |||||
// Serialize the PSBT | // Serialize the PSBT | ||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); | CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); | ||||
ssTx << psbtx; | ssTx << psbtx; | ||||
UniValue result(UniValue::VOBJ); | UniValue result(UniValue::VOBJ); | ||||
result.pushKV("psbt", EncodeBase64((uint8_t *)ssTx.data(), ssTx.size())); | result.pushKV("psbt", EncodeBase64(ssTx.str())); | ||||
result.pushKV("fee", ValueFromAmount(fee)); | result.pushKV("fee", ValueFromAmount(fee)); | ||||
result.pushKV("changepos", change_position); | result.pushKV("changepos", change_position); | ||||
return result; | return result; | ||||
} | } | ||||
// clang-format off | // clang-format off | ||||
static const ContextFreeRPCCommand commands[] = { | static const ContextFreeRPCCommand commands[] = { | ||||
// category name actor (function) argNames | // category name actor (function) argNames | ||||
▲ Show 20 Lines • Show All 54 Lines • Show Last 20 Lines |