mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-19 13:27:35 +02:00
fundrawtransaction basics
This commit is contained in:
parent
625eff80e9
commit
018828d666
10 changed files with 146 additions and 10 deletions
|
|
@ -26,6 +26,7 @@ if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
|
|||
${BUILDDIR}/qa/rpc-tests/mempool_spendcoinbase.py --srcdir "${BUILDDIR}/src"
|
||||
${BUILDDIR}/qa/rpc-tests/httpbasics.py --srcdir "${BUILDDIR}/src"
|
||||
${BUILDDIR}/qa/rpc-tests/mempool_coinbase_spends.py --srcdir "${BUILDDIR}/src"
|
||||
${BUILDDIR}/qa/rpc-tests/rawtransactions.py --srcdir "${BUILDDIR}/src"
|
||||
#${BUILDDIR}/qa/rpc-tests/forknotify.py --srcdir "${BUILDDIR}/src"
|
||||
else
|
||||
echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"
|
||||
|
|
|
|||
52
qa/rpc-tests/rawtransactions.py
Executable file
52
qa/rpc-tests/rawtransactions.py
Executable file
|
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#
|
||||
# Test re-org scenarios with a mempool that contains transactions
|
||||
# that spend (directly or indirectly) coinbase transactions.
|
||||
#
|
||||
|
||||
from test_framework import BitcoinTestFramework
|
||||
from util import *
|
||||
|
||||
# Create one-input, one-output, no-fee transaction:
|
||||
class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
def run_test(self):
|
||||
|
||||
newAddr = self.nodes[2].getnewaddress()
|
||||
|
||||
inputs = []
|
||||
outputs = { newAddr : 10 }
|
||||
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
rawtxfund = self.nodes[0].fundrawtransaction(rawtx)
|
||||
dec_rawtxfund = self.nodes[0].decoderawtransaction(rawtxfund['hex'])
|
||||
|
||||
assert_equal(len(dec_rawtxfund['vin']), 1)
|
||||
assert_equal(len(dec_rawtxfund['vout']), 2)
|
||||
assert_equal(rawtxfund['fee'] > 0, True)
|
||||
assert_equal(dec_rawtxfund['vin'][0]['scriptSig']['hex'], '')
|
||||
|
||||
rawtxfundsigned = self.nodes[0].signrawtransaction(rawtxfund['hex'])
|
||||
dec_rawtxfundsigned = self.nodes[0].decoderawtransaction(rawtxfundsigned['hex'])
|
||||
|
||||
assert_equal(len(dec_rawtxfundsigned['vin'][0]['scriptSig']['hex']) > 20, True)
|
||||
|
||||
|
||||
listunspent = self.nodes[2].listunspent()
|
||||
inputs = [{'txid' : listunspent[0]['txid'], 'vout' : listunspent[0]['vout']}]
|
||||
outputs = { newAddr : 10 }
|
||||
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
aException = False
|
||||
try:
|
||||
rawtxfund = self.nodes[0].fundrawtransaction(rawtx)
|
||||
except JSONRPCException,e:
|
||||
aException = True
|
||||
|
||||
assert_equal(aException, True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
RawTransactionsTest().main()
|
||||
|
|
@ -263,8 +263,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
|
|||
std::string strFailReason;
|
||||
|
||||
CWalletTx *newTx = transaction.getTransaction();
|
||||
CMutableTransaction newMTx;
|
||||
CReserveKey *keyChange = transaction.getPossibleKeyChange();
|
||||
bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason, coinControl);
|
||||
bool fCreated = wallet->CreateTransaction(vecSend, *newTx, newMTx, *keyChange, nFeeRequired, strFailReason, coinControl);
|
||||
transaction.setTransactionFee(nFeeRequired);
|
||||
|
||||
if(!fCreated)
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "signrawtransaction", 1 },
|
||||
{ "signrawtransaction", 2 },
|
||||
{ "sendrawtransaction", 1 },
|
||||
{ "fundrawtransaction", 1 },
|
||||
{ "gettxout", 1 },
|
||||
{ "gettxout", 2 },
|
||||
{ "lockunspent", 0 },
|
||||
|
|
|
|||
|
|
@ -756,3 +756,57 @@ Value sendrawtransaction(const Array& params, bool fHelp)
|
|||
|
||||
return hashTx.GetHex();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
Value fundrawtransaction(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"fundrawtransaction \"hexstring\"\n"
|
||||
"\nAdd vIns to a raw transaction.\n"
|
||||
"\nAlso see createrawtransaction and signrawtransaction calls.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"hex\": \"value\", (string) The raw transaction with vIns (hex-encoded string)\n"
|
||||
" \"fee\": n calculated fee\n"
|
||||
"}\n"
|
||||
"\"hex\" \n"
|
||||
"\nExamples:\n"
|
||||
"\nCreate a transaction with empty vIns\n"
|
||||
+ HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
|
||||
"\nFund the transaction, and get back the hex\n"
|
||||
+ HelpExampleCli("fundrawtransaction", "\"myhex\"") +
|
||||
"\nSign the transaction, and get back the hex\n"
|
||||
+ HelpExampleCli("signrawtransaction", "\"myhex\"") +
|
||||
"\nSend the transaction (signed hex)\n"
|
||||
+ HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
|
||||
"\nAs a json rpc call\n"
|
||||
+ HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
|
||||
);
|
||||
|
||||
RPCTypeCheck(params, list_of(str_type)(bool_type));
|
||||
|
||||
// parse hex string from parameter
|
||||
CTransaction tx;
|
||||
if (!DecodeHexTx(tx, params[0].get_str()))
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
|
||||
|
||||
if (tx.vin.size() > 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "fundrawtransaction only supports transactions with zero exiting vins");
|
||||
|
||||
CMutableTransaction txNew;
|
||||
CAmount nFeeRet;
|
||||
string strFailReason;
|
||||
if(!pwalletMain->FundTransaction(tx, txNew, nFeeRet, strFailReason))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
|
||||
|
||||
Object result;
|
||||
result.push_back(Pair("hex", EncodeHexTx(txNew)));
|
||||
result.push_back(Pair("fee", nFeeRet));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -293,7 +293,10 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "rawtransactions", "getrawtransaction", &getrawtransaction, true, false, false },
|
||||
{ "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, false, false },
|
||||
{ "rawtransactions", "signrawtransaction", &signrawtransaction, false, false, false }, /* uses wallet if enabled */
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, false, false, true },
|
||||
#endif
|
||||
|
||||
/* Utility functions */
|
||||
{ "util", "createmultisig", &createmultisig, true, true , false },
|
||||
{ "util", "validateaddress", &validateaddress, true, false, false }, /* uses wallet if enabled */
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ extern json_spirit::Value listlockunspent(const json_spirit::Array& params, bool
|
|||
extern json_spirit::Value createrawtransaction(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value decoderawtransaction(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value decodescript(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value fundrawtransaction(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value signrawtransaction(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value sendrawtransaction(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
|
|
|
|||
|
|
@ -901,7 +901,8 @@ Value sendmany(const Array& params, bool fHelp)
|
|||
CReserveKey keyChange(pwalletMain);
|
||||
CAmount nFeeRequired = 0;
|
||||
string strFailReason;
|
||||
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason);
|
||||
CMutableTransaction newTx;
|
||||
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, newTx, keyChange, nFeeRequired, strFailReason);
|
||||
if (!fCreated)
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
|
||||
if (!pwalletMain->CommitTransaction(wtx, keyChange))
|
||||
|
|
|
|||
|
|
@ -1358,10 +1358,23 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
|
|||
}
|
||||
|
||||
|
||||
|
||||
bool CWallet::FundTransaction(const CTransaction& txToFund, CMutableTransaction& txNew, CAmount &nFeeRet, std::string& strFailReason)
|
||||
{
|
||||
|
||||
vector<pair<CScript, CAmount> > vecSend;
|
||||
|
||||
BOOST_FOREACH (const CTxOut& out, txToFund.vout)
|
||||
{
|
||||
vecSend.push_back(make_pair(out.scriptPubKey, out.nValue));
|
||||
}
|
||||
|
||||
CReserveKey reservekey(this);
|
||||
CWalletTx wtx;
|
||||
return CreateTransaction(vecSend, wtx, txNew, reservekey, nFeeRet, strFailReason, NULL, false);
|
||||
}
|
||||
|
||||
bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
|
||||
CWalletTx& wtxNew, CMutableTransaction& txNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
|
||||
{
|
||||
CAmount nValue = 0;
|
||||
BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
|
||||
|
|
@ -1381,7 +1394,6 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
|
|||
|
||||
wtxNew.fTimeReceivedIsTxTime = true;
|
||||
wtxNew.BindWallet(this);
|
||||
CMutableTransaction txNew;
|
||||
|
||||
{
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
|
|
@ -1502,6 +1514,14 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
|
|||
strFailReason = _("Transaction too large");
|
||||
return false;
|
||||
}
|
||||
|
||||
//remove signature if we used the signing only for the fee calculation
|
||||
if(!sign)
|
||||
{
|
||||
BOOST_FOREACH (CTxIn& vin, txNew.vin)
|
||||
vin.scriptSig = CScript();
|
||||
}
|
||||
|
||||
dPriority = wtxNew.ComputePriority(dPriority, nBytes);
|
||||
|
||||
// Can we complete this as a free transaction?
|
||||
|
|
@ -1541,11 +1561,12 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
|
|||
}
|
||||
|
||||
bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
|
||||
{
|
||||
vector< pair<CScript, CAmount> > vecSend;
|
||||
vecSend.push_back(make_pair(scriptPubKey, nValue));
|
||||
return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl);
|
||||
CMutableTransaction txNew;
|
||||
return CreateTransaction(vecSend, wtxNew, txNew, reservekey, nFeeRet, strFailReason, coinControl, sign);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -288,10 +288,11 @@ public:
|
|||
CAmount GetWatchOnlyBalance() const;
|
||||
CAmount GetUnconfirmedWatchOnlyBalance() const;
|
||||
CAmount GetImmatureWatchOnlyBalance() const;
|
||||
bool FundTransaction(const CTransaction& txToFund, CMutableTransaction& txNew, CAmount& nFeeRet, std::string& strFailReason);
|
||||
bool CreateTransaction(const std::vector<std::pair<CScript, CAmount> >& vecSend,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
|
||||
CWalletTx& wtxNew, CMutableTransaction& txNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = false);
|
||||
bool CreateTransaction(CScript scriptPubKey, const CAmount& nValue,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = false);
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
|
||||
|
||||
static CFeeRate minTxFee;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue