Browse Source

remove rpc crypto conditions

pull/4/head
Scott Sadler 6 years ago
parent
commit
a01d0f5672
  1. 1
      src/Makefile.am
  2. 4
      src/rpcclient.cpp
  3. 848
      src/rpccryptoconditions.cpp
  4. 2
      src/rpcserver.cpp
  5. 3
      src/rpcserver.h

1
src/Makefile.am

@ -238,7 +238,6 @@ libbitcoin_server_a_SOURCES = \
rpcmisc.cpp \
rpcnet.cpp \
rpcrawtransaction.cpp \
rpccryptoconditions.cpp \
rpcserver.cpp \
script/sigcache.cpp \
timedata.cpp \

4
src/rpcclient.cpp

@ -75,12 +75,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getrawtransaction", 1 },
{ "createrawtransaction", 0 },
{ "createrawtransaction", 1 },
{ "createrawtransactioncc", 0 },
{ "createrawtransactioncc", 1 },
{ "signrawtransaction", 1 },
{ "signrawtransaction", 2 },
{ "signrawtransactioncc", 1 },
{ "signrawtransactioncc", 2 },
{ "sendrawtransaction", 1 },
{ "fundrawtransaction", 1 },
{ "gettxout", 1 },

848
src/rpccryptoconditions.cpp

@ -1,848 +0,0 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
#include "consensus/validation.h"
#include "core_io.h"
#include "init.h"
#include "keystore.h"
#include "main.h"
#include "merkleblock.h"
#include "net.h"
#include "primitives/transaction.h"
#include "rpcserver.h"
#include "script/script.h"
#include "script/script_error.h"
#include "script/sign.h"
#include "script/standard.h"
#include "uint256.h"
#include "cryptoconditions/include/cryptoconditions.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif
#include <stdint.h>
#include <boost/assign/list_of.hpp>
#include <univalue.h>
using namespace std;
void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
UniValue TxJoinSplitToJSONcc(const CTransaction& tx) {
UniValue vjoinsplit(UniValue::VARR);
for (unsigned int i = 0; i < tx.vjoinsplit.size(); i++) {
const JSDescription& jsdescription = tx.vjoinsplit[i];
UniValue joinsplit(UniValue::VOBJ);
joinsplit.push_back(Pair("vpub_old", ValueFromAmount(jsdescription.vpub_old)));
joinsplit.push_back(Pair("vpub_new", ValueFromAmount(jsdescription.vpub_new)));
joinsplit.push_back(Pair("anchor", jsdescription.anchor.GetHex()));
{
UniValue nullifiers(UniValue::VARR);
BOOST_FOREACH(const uint256 nf, jsdescription.nullifiers) {
nullifiers.push_back(nf.GetHex());
}
joinsplit.push_back(Pair("nullifiers", nullifiers));
}
{
UniValue commitments(UniValue::VARR);
BOOST_FOREACH(const uint256 commitment, jsdescription.commitments) {
commitments.push_back(commitment.GetHex());
}
joinsplit.push_back(Pair("commitments", commitments));
}
joinsplit.push_back(Pair("onetimePubKey", jsdescription.ephemeralKey.GetHex()));
joinsplit.push_back(Pair("randomSeed", jsdescription.randomSeed.GetHex()));
{
UniValue macs(UniValue::VARR);
BOOST_FOREACH(const uint256 mac, jsdescription.macs) {
macs.push_back(mac.GetHex());
}
joinsplit.push_back(Pair("macs", macs));
}
CDataStream ssProof(SER_NETWORK, PROTOCOL_VERSION);
ssProof << jsdescription.proof;
joinsplit.push_back(Pair("proof", HexStr(ssProof.begin(), ssProof.end())));
{
UniValue ciphertexts(UniValue::VARR);
for (const ZCNoteEncryption::Ciphertext ct : jsdescription.ciphertexts) {
ciphertexts.push_back(HexStr(ct.begin(), ct.end()));
}
joinsplit.push_back(Pair("ciphertexts", ciphertexts));
}
vjoinsplit.push_back(joinsplit);
}
return vjoinsplit;
}
uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
UniValue getrawtransactioncc(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"getrawtransaction \"txid\" ( verbose )\n"
"\nNOTE: By default this function only works sometimes. This is when the tx is in the mempool\n"
"or there is an unspent output in the utxo for this transaction. To make it always work,\n"
"you need to maintain a transaction index, using the -txindex command line option.\n"
"\nReturn the raw transaction data.\n"
"\nIf verbose=0, returns a string that is serialized, hex-encoded data for 'txid'.\n"
"If verbose is non-zero, returns an Object with information about 'txid'.\n"
"\nArguments:\n"
"1. \"txid\" (string, required) The transaction id\n"
"2. verbose (numeric, optional, default=0) If 0, return a string, other return a json object\n"
"\nResult (if verbose is not set or set to 0):\n"
"\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
"\nResult (if verbose > 0):\n"
"{\n"
" \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n"
" \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
" \"version\" : n, (numeric) The version\n"
" \"locktime\" : ttt, (numeric) The lock time\n"
" \"vin\" : [ (array of json objects)\n"
" {\n"
" \"txid\": \"id\", (string) The transaction id\n"
" \"vout\": n, (numeric) \n"
" \"scriptSig\": { (json object) The script\n"
" \"asm\": \"asm\", (string) asm\n"
" \"hex\": \"hex\" (string) hex\n"
" },\n"
" \"sequence\": n (numeric) The script sequence number\n"
" }\n"
" ,...\n"
" ],\n"
" \"vout\" : [ (array of json objects)\n"
" {\n"
" \"value\" : x.xxx, (numeric) The value in btc\n"
" \"n\" : n, (numeric) index\n"
" \"scriptPubKey\" : { (json object)\n"
" \"asm\" : \"asm\", (string) the asm\n"
" \"hex\" : \"hex\", (string) the hex\n"
" \"reqSigs\" : n, (numeric) The required sigs\n"
" \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
" \"addresses\" : [ (json array of string)\n"
" \"bitcoinaddress\" (string) bitcoin address\n"
" ,...\n"
" ]\n"
" }\n"
" }\n"
" ,...\n"
" ],\n"
" \"vjoinsplit\" : [ (array of json objects, only for version >= 2)\n"
" {\n"
" \"vpub_old\" : x.xxx, (numeric) public input value in ZEC\n"
" \"vpub_new\" : x.xxx, (numeric) public output value in ZEC\n"
" \"anchor\" : \"hex\", (string) the anchor\n"
" \"nullifiers\" : [ (json array of string)\n"
" \"hex\" (string) input note nullifier\n"
" ,...\n"
" ],\n"
" \"commitments\" : [ (json array of string)\n"
" \"hex\" (string) output note commitment\n"
" ,...\n"
" ],\n"
" \"onetimePubKey\" : \"hex\", (string) the onetime public key used to encrypt the ciphertexts\n"
" \"randomSeed\" : \"hex\", (string) the random seed\n"
" \"macs\" : [ (json array of string)\n"
" \"hex\" (string) input note MAC\n"
" ,...\n"
" ],\n"
" \"proof\" : \"hex\", (string) the zero-knowledge proof\n"
" \"ciphertexts\" : [ (json array of string)\n"
" \"hex\" (string) output note ciphertext\n"
" ,...\n"
" ]\n"
" }\n"
" ,...\n"
" ],\n"
" \"blockhash\" : \"hash\", (string) the block hash\n"
" \"confirmations\" : n, (numeric) The confirmations\n"
" \"time\" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getrawtransaction", "\"mytxid\"")
+ HelpExampleCli("getrawtransaction", "\"mytxid\" 1")
+ HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")
);
LOCK(cs_main);
uint256 hash = ParseHashV(params[0], "parameter 1");
bool fVerbose = false;
if (params.size() > 1)
fVerbose = (params[1].get_int() != 0);
CTransaction tx;
uint256 hashBlock;
if (!GetTransaction(hash, tx, hashBlock, true))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
string strHex = EncodeHexTx(tx);
if (!fVerbose)
return strHex;
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", strHex));
TxToJSON(tx, hashBlock, result);
return result;
}
int32_t gettxout_scriptPubKeycc(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n)
{
int32_t i,m; uint8_t *ptr;
LOCK(cs_main);
/*CCoins coins;
for (iter=0; iter<2; iter++)
{
if ( iter == 0 )
{
LOCK(mempool.cs);
CCoinsViewMemPool view(pcoinsTip,mempool);
if ( view.GetCoins(txid,coins) == 0 )
{
//fprintf(stderr,"cant get view\n");
continue;
}
mempool.pruneSpent(txid, coins); // TODO: this should be done by the CCoinsViewMemPool
}
else if ( pcoinsTip->GetCoins(txid,coins) == 0 )
{
//fprintf(stderr,"cant get pcoinsTip->GetCoins\n");
continue;
}
if ( n < 0 || (unsigned int)n >= coins.vout.size() || coins.vout[n].IsNull() )
{
fprintf(stderr,"iter.%d n.%d vs voutsize.%d\n",iter,n,(int32_t)coins.vout.size());
continue;
}
ptr = (uint8_t *)coins.vout[n].scriptPubKey.data();
m = coins.vout[n].scriptPubKey.size();
for (i=0; i<maxsize&&i<m; i++)
scriptPubKey[i] = ptr[i];
return(i);
}*/
CTransaction tx;
uint256 hashBlock;
if ( GetTransaction(txid,tx,hashBlock,true) == 0 )
return(-1);
else if ( n <= tx.vout.size() ) // vout.size() seems off by 1
{
ptr = (uint8_t *)tx.vout[n].scriptPubKey.data();
m = tx.vout[n].scriptPubKey.size();
for (i=0; i<maxsize&&i<m; i++)
scriptPubKey[i] = ptr[i];
//fprintf(stderr,"got scriptPubKey via rawtransaction\n");
return(i);
}
return(-1);
}
UniValue gettxoutproofcc(const UniValue& params, bool fHelp)
{
if (fHelp || (params.size() != 1 && params.size() != 2))
throw runtime_error(
"gettxoutproof [\"txid\",...] ( blockhash )\n"
"\nReturns a hex-encoded proof that \"txid\" was included in a block.\n"
"\nNOTE: By default this function only works sometimes. This is when there is an\n"
"unspent output in the utxo for this transaction. To make it always work,\n"
"you need to maintain a transaction index, using the -txindex command line option or\n"
"specify the block in which the transaction is included in manually (by blockhash).\n"
"\nReturn the raw transaction data.\n"
"\nArguments:\n"
"1. \"txids\" (string) A json array of txids to filter\n"
" [\n"
" \"txid\" (string) A transaction hash\n"
" ,...\n"
" ]\n"
"2. \"block hash\" (string, optional) If specified, looks for txid in the block with this hash\n"
"\nResult:\n"
"\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n"
);
set<uint256> setTxids;
uint256 oneTxid;
UniValue txids = params[0].get_array();
for (size_t idx = 0; idx < txids.size(); idx++) {
const UniValue& txid = txids[idx];
if (txid.get_str().length() != 64 || !IsHex(txid.get_str()))
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid txid ")+txid.get_str());
uint256 hash(uint256S(txid.get_str()));
if (setTxids.count(hash))
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated txid: ")+txid.get_str());
setTxids.insert(hash);
oneTxid = hash;
}
LOCK(cs_main);
CBlockIndex* pblockindex = NULL;
uint256 hashBlock;
if (params.size() > 1)
{
hashBlock = uint256S(params[1].get_str());
if (!mapBlockIndex.count(hashBlock))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
pblockindex = mapBlockIndex[hashBlock];
} else {
CCoins coins;
if (pcoinsTip->GetCoins(oneTxid, coins) && coins.nHeight > 0 && coins.nHeight <= chainActive.Height())
pblockindex = chainActive[coins.nHeight];
}
if (pblockindex == NULL)
{
CTransaction tx;
if (!GetTransaction(oneTxid, tx, hashBlock, false) || hashBlock.IsNull())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
if (!mapBlockIndex.count(hashBlock))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
pblockindex = mapBlockIndex[hashBlock];
}
CBlock block;
if(!ReadBlockFromDisk(block, pblockindex))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
unsigned int ntxFound = 0;
BOOST_FOREACH(const CTransaction&tx, block.vtx)
if (setTxids.count(tx.GetHash()))
ntxFound++;
if (ntxFound != setTxids.size())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "(Not all) transactions not found in specified block");
CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION);
CMerkleBlock mb(block, setTxids);
ssMB << mb;
std::string strHex = HexStr(ssMB.begin(), ssMB.end());
return strHex;
}
UniValue verifytxoutproofcc(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"verifytxoutproof \"proof\"\n"
"\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n"
"and throwing an RPC error if the block is not in our best chain\n"
"\nArguments:\n"
"1. \"proof\" (string, required) The hex-encoded proof generated by gettxoutproof\n"
"\nResult:\n"
"[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n"
);
CDataStream ssMB(ParseHexV(params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION);
CMerkleBlock merkleBlock;
ssMB >> merkleBlock;
UniValue res(UniValue::VARR);
vector<uint256> vMatch;
if (merkleBlock.txn.ExtractMatches(vMatch) != merkleBlock.header.hashMerkleRoot)
return res;
LOCK(cs_main);
if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()]))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
BOOST_FOREACH(const uint256& hash, vMatch)
res.push_back(hash.GetHex());
return res;
}
CC *ConditionFromString(std::string encoded) {
char *err = new char[1000];
CC *cond = cc_conditionFromJSONString(encoded.c_str(), err);
if (NULL == cond)
throw JSONRPCError(RPC_INVALID_PARAMETER, err);
}
CC *ConditionFromCharVector(vector<unsigned char>& vch) {
return ConditionFromString(std::string(vch.begin(), vch.end()));
}
CC *ConditionFromUnsignedInputScript(const CScript& script)
{
opcodetype op;
CScript::const_iterator it = script.begin();
vector<unsigned char> vch;
if (script.GetOp2(it, op, &vch)) {
if (vch.at(0) == '{') {
return ConditionFromCharVector(vch);
}
}
return NULL;
}
CC *ConditionFromValue(UniValue value) {
std::string conditionEncoded = value.write();
// TODO: Is null?
return ConditionFromString(conditionEncoded);
}
UniValue createrawtransactioncc(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 2)
throw runtime_error(
"createrawtransactioncc [{\"txid\":\"id\",\"vout\":n,\"fulfillment\":{...}},...] {\"address\":amount,...}\n"
"\nCreate a transaction spending the given inputs and sending to the given addresses.\n"
"Returns hex-encoded raw transaction.\n"
"Note that the transaction's inputs are not signed, and\n"
"it is not stored in the wallet or transmitted to the network.\n"
"\nArguments:\n"
"1. \"inputs\" (string, required) A json array of json objects\n"
" [\n"
" {\n"
" \"txid\":\"id\", (string, required) The transaction id\n"
" \"vout\":n, (numeric, required) The output number\n"
" \"fulfillment\":{...} (object, required) The JSON encoded cryptocondition fulfillment for the previous transaction's output\n"
" }\n"
" ,...\n"
" ]\n"
"2. \"outputs\" (string, required) a json array with addresses as keys and amounts as values\n"
" {\n"
" \"condition\":\"{...}\" (object, required) The JSON encoded condition\n"
" \"amount\":n, (numeric, required) The coin amount in satoshis\n"
" }\n"
"\nResult:\n"
"\"transaction\" (string) hex string of the transaction\n"
// "\nExamples\n"
// + HelpExampleCli("createrawtransactioncc", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"")
// + HelpExampleRpc("createrawtransactioncc", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"")
);
LOCK(cs_main);
//RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VARR));
UniValue inputs = params[0].get_array();
UniValue outputs = params[1].get_array();
CMutableTransaction rawTx;
for (size_t idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
const UniValue& o = input.get_obj();
uint256 txid = ParseHashO(o, "txid");
const UniValue& vout_v = find_value(o, "vout");
if (!vout_v.isNum())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
int nOutput = vout_v.get_int();
if (nOutput < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
const UniValue& ffill_v = find_value(input, "fulfillment");
if (!ffill_v.isObject()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "\"fulfillment\" missing or not an object");
}
const std::string ffillEncoded = ffill_v.write();
// Validate the fulfillment
CC *cond = ConditionFromString(ffillEncoded);
if (cond == NULL) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "\"fulfillment\" not a valid JSON encoded crypto condition");
}
cc_free(cond);
CScript inputScript;
const std::vector<unsigned char> ffill(ffillEncoded.c_str(), ffillEncoded.c_str() + ffillEncoded.size());
inputScript << ffill;
CTxIn in(COutPoint(txid, nOutput), inputScript);
rawTx.vin.push_back(in);
}
for (size_t idx = 0; idx < outputs.size(); idx++) {
const UniValue& output = outputs[idx].get_obj();
// This does not need to be fulfilled, we just want the condition binary
CC *cond = ConditionFromValue(find_value(output, "condition"));
char *condBin = new char[1000];
size_t binLength = cc_conditionBinary(cond, condBin);
const std::vector<unsigned char> condVec(condBin, condBin + binLength);
CScript redeemScript;
redeemScript << condVec << OP_CHECKCRYPTOCONDITIONVERIFY;
CAmount nAmount = AmountFromValue(find_value(output, "amount"));
CTxOut out(nAmount, redeemScript);
rawTx.vout.push_back(out);
}
return EncodeHexTx(rawTx);
}
UniValue decoderawtransactioncc(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"decoderawtransaction \"hexstring\"\n"
"\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
"\nArguments:\n"
"1. \"hex\" (string, required) The transaction hex string\n"
"\nResult:\n"
"{\n"
" \"txid\" : \"id\", (string) The transaction id\n"
" \"version\" : n, (numeric) The version\n"
" \"locktime\" : ttt, (numeric) The lock time\n"
" \"vin\" : [ (array of json objects)\n"
" {\n"
" \"txid\": \"id\", (string) The transaction id\n"
" \"vout\": n, (numeric) The output number\n"
" \"scriptSig\": { (json object) The script\n"
" \"asm\": \"asm\", (string) asm\n"
" \"hex\": \"hex\" (string) hex\n"
" },\n"
" \"sequence\": n (numeric) The script sequence number\n"
" }\n"
" ,...\n"
" ],\n"
" \"vout\" : [ (array of json objects)\n"
" {\n"
" \"value\" : x.xxx, (numeric) The value in btc\n"
" \"n\" : n, (numeric) index\n"
" \"scriptPubKey\" : { (json object)\n"
" \"asm\" : \"asm\", (string) the asm\n"
" \"hex\" : \"hex\", (string) the hex\n"
" \"reqSigs\" : n, (numeric) The required sigs\n"
" \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
" \"addresses\" : [ (json array of string)\n"
" \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) bitcoin address\n"
" ,...\n"
" ]\n"
" }\n"
" }\n"
" ,...\n"
" ],\n"
" \"vjoinsplit\" : [ (array of json objects, only for version >= 2)\n"
" {\n"
" \"vpub_old\" : x.xxx, (numeric) public input value in ZEC\n"
" \"vpub_new\" : x.xxx, (numeric) public output value in ZEC\n"
" \"anchor\" : \"hex\", (string) the anchor\n"
" \"nullifiers\" : [ (json array of string)\n"
" \"hex\" (string) input note nullifier\n"
" ,...\n"
" ],\n"
" \"commitments\" : [ (json array of string)\n"
" \"hex\" (string) output note commitment\n"
" ,...\n"
" ],\n"
" \"onetimePubKey\" : \"hex\", (string) the onetime public key used to encrypt the ciphertexts\n"
" \"randomSeed\" : \"hex\", (string) the random seed\n"
" \"macs\" : [ (json array of string)\n"
" \"hex\" (string) input note MAC\n"
" ,...\n"
" ],\n"
" \"proof\" : \"hex\", (string) the zero-knowledge proof\n"
" \"ciphertexts\" : [ (json array of string)\n"
" \"hex\" (string) output note ciphertext\n"
" ,...\n"
" ]\n"
" }\n"
" ,...\n"
" ],\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("decoderawtransaction", "\"hexstring\"")
+ HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
);
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
CTransaction tx;
if (!DecodeHexTx(tx, params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
UniValue result(UniValue::VOBJ);
TxToJSON(tx, uint256(), result);
return result;
}
/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage) {}
UniValue signrawtransactioncc(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"signrawtransactioncc \"hexstring\" ( [\"privatekey1\",...] sighashtype )\n"
"\nSign cryptocondition inputs for raw transaction (serialized, hex-encoded).\n"
"The second optional argument (may be null) is an array of previous transaction outputs that\n"
"this transaction depends on but may not yet be in the block chain.\n"
"The third optional argument (may be null) is an array of base58-encoded private\n"
"keys that, if given, will be the only keys used to sign the transaction.\n"
#ifdef ENABLE_WALLET
+ HelpRequiringPassphrase() + "\n"
#endif
"\nArguments:\n"
"1. \"hexstring\" (string, required) The transaction hex string\n"
"2. \"privatekeys\" (string, optional) A json array of base58-encoded private keys for signing\n"
" [ (json array of strings, or 'null' if none provided)\n"
" \"privatekey\" (string) private key in base58-encoding\n"
" ,...\n"
" ]\n"
/* "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
" \"ALL\"\n"
" \"NONE\"\n"
" \"SINGLE\"\n"
" \"ALL|ANYONECANPAY\"\n"
" \"NONE|ANYONECANPAY\"\n"
" \"SINGLE|ANYONECANPAY\"\n" */
"\nResult:\n"
"{\n"
" \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
" \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n"
" {\n"
" \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n"
" \"vout\" : n, (numeric) The index of the output to spent and used as input\n"
" \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n"
" \"sequence\" : n, (numeric) Script sequence number\n"
" \"error\" : \"text\" (string) Verification or signing error related to the input\n"
" }\n"
" ,...\n"
" ]\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("signrawtransactioncc", "\"myhex\"")
+ HelpExampleRpc("signrawtransactioncc", "\"myhex\"")
);
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VARR)(UniValue::VARR)(UniValue::VSTR), true);
vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
vector<CMutableTransaction> txVariants;
while (!ssData.empty()) {
//try {
CMutableTransaction tx;
ssData >> tx;
txVariants.push_back(tx);
//}
//catch (const std::exception&) {
//throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
//}
}
if (txVariants.empty())
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
// mergedTx will end up with all the signatures; it
// starts as a clone of the rawtx:
CMutableTransaction mergedTx(txVariants[0]);
bool fGivenKeys = false;
CBasicKeyStore tempKeystore;
if (params.size() > 2 && !params[2].isNull()) {
fGivenKeys = true;
UniValue keys = params[2].get_array();
for (size_t idx = 0; idx < keys.size(); idx++) {
UniValue k = keys[idx];
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(k.get_str());
if (!fGood)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
CKey key = vchSecret.GetKey();
if (!key.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
tempKeystore.AddKey(key);
}
}
#ifdef ENABLE_WALLET
else if (pwalletMain)
EnsureWalletIsUnlocked();
#endif
#ifdef ENABLE_WALLET
const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
#else
const CKeyStore& keystore = tempKeystore;
#endif
int nHashType = SIGHASH_ALL;
/*
if (params.size() > 3 && !params[3].isNull()) {
static map<string, int> mapSigHashValues =
boost::assign::map_list_of
(string("ALL"), int(SIGHASH_ALL))
(string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
(string("NONE"), int(SIGHASH_NONE))
(string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
(string("SINGLE"), int(SIGHASH_SINGLE))
(string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
;
string strHashType = params[3].get_str();
if (mapSigHashValues.count(strHashType))
nHashType = mapSigHashValues[strHashType];
else
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
}
*/
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
// Script verification errors
UniValue vErrors(UniValue::VARR);
// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
CTxIn& txin = mergedTx.vin[i];
CC *cond;
printf("Go\n");
if (cond = ConditionFromUnsignedInputScript(txin.scriptSig)) {
printf("Found unsigned\n");
continue;
}
printf("No luck\n");
/*
* Replace all this with detection of cryptoconditions spec and signing with each privkey
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
if (coins == NULL || !coins->IsAvailable(txin.prevout.n)) {
TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
continue;
}
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
txin.scriptSig.clear();
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mergedTx.vout.size()))
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
// ... and merge in other signatures:
BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
}
ScriptError serror = SCRIPT_ERR_OK;
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i), &serror)) {
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
}
*/
}
bool fComplete = vErrors.empty();
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
result.push_back(Pair("complete", fComplete));
if (!vErrors.empty()) {
result.push_back(Pair("errors", vErrors));
}
return result;
}
UniValue sendrawtransactioncc(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"sendrawtransaction \"hexstring\" ( allowhighfees )\n"
"\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n"
"\nAlso see createrawtransactioncc and signrawtransactioncc calls.\n"
"\nArguments:\n"
"1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
"2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
"\nResult:\n"
"\"hex\" (string) The transaction hash in hex\n"
"\nExamples:\n"
"\nCreate a transaction\n"
+ HelpExampleCli("createrawtransactioncc", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
"Sign 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\"")
);
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
// parse hex string from parameter
CTransaction tx;
if (!DecodeHexTx(tx, params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
uint256 hashTx = tx.GetHash();
bool fOverrideFees = false;
if (params.size() > 1)
fOverrideFees = params[1].get_bool();
CCoinsViewCache &view = *pcoinsTip;
const CCoins* existingCoins = view.AccessCoins(hashTx);
bool fHaveMempool = mempool.exists(hashTx);
bool fHaveChain = existingCoins && existingCoins->nHeight < 1000000000;
if (!fHaveMempool && !fHaveChain) {
// push to local node and sync with wallets
CValidationState state;
bool fMissingInputs;
if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees)) {
if (state.IsInvalid()) {
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else {
if (fMissingInputs) {
throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
}
throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason());
}
}
} else if (fHaveChain) {
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
}
RelayTransaction(tx);
return hashTx.GetHex();
}

2
src/rpcserver.cpp

@ -325,8 +325,6 @@ static const CRPCCommand vRPCCommands[] =
{ "rawtransactions", "getrawtransaction", &getrawtransaction, true },
{ "rawtransactions", "sendrawtransaction", &sendrawtransaction, false },
{ "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */
{ "rawtransactions", "createrawtransactioncc", &createrawtransactioncc, true },
{ "rawtransactions", "signrawtransactioncc", &signrawtransactioncc, false }, /* uses wallet if enabled */
#ifdef ENABLE_WALLET
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, false },
#endif

3
src/rpcserver.h

@ -262,9 +262,6 @@ extern UniValue sendrawtransaction(const UniValue& params, bool fHelp);
extern UniValue gettxoutproof(const UniValue& params, bool fHelp);
extern UniValue verifytxoutproof(const UniValue& params, bool fHelp);
extern UniValue createrawtransactioncc(const UniValue& params, bool fHelp); // in rpccryptocondition.cpp
extern UniValue signrawtransactioncc(const UniValue& params, bool fHelp);
extern UniValue getblockcount(const UniValue& params, bool fHelp); // in rpcblockchain.cpp
extern UniValue getbestblockhash(const UniValue& params, bool fHelp);
extern UniValue getdifficulty(const UniValue& params, bool fHelp);

Loading…
Cancel
Save