aboutsummaryrefslogtreecommitdiff
path: root/src/bitcoinrpc.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2011-10-03 13:05:43 -0400
committerGavin Andresen <gavinandresen@gmail.com>2011-12-19 12:40:19 -0500
commite679ec969c8b22c676ebb10bea1038f6c8f13b33 (patch)
treec584f1a152c376ca0df93261d447c5b719449508 /src/bitcoinrpc.cpp
parentcc40ba2151a627b6da9af4932e0bee58e69aacb5 (diff)
OP_EVAL implementation
OP_EVAL is a new opcode that evaluates an item on the stack as a script. It enables a new type of bitcoin address that needs an arbitrarily complex script to redeem.
Diffstat (limited to 'src/bitcoinrpc.cpp')
-rw-r--r--src/bitcoinrpc.cpp122
1 files changed, 52 insertions, 70 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 122bf61b8f..3e42e70387 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -667,7 +667,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
if (params.size() > 1)
nMinDepth = params[1].get_int();
- // Get the set of pub keys that have the label
+ // Get the set of pub keys assigned to account
string strAccount = AccountFromValue(params[0]);
set<CBitcoinAddress> setAddress;
GetAccountAddresses(strAccount, setAddress);
@@ -936,56 +936,30 @@ Value sendmany(const Array& params, bool fHelp)
return wtx.GetHash().GetHex();
}
-Value sendmultisig(const Array& params, bool fHelp)
+Value addmultisigaddress(const Array& params, bool fHelp)
{
- if (fHelp || params.size() < 4 || params.size() > 7)
+ if (fHelp || params.size() < 2 || params.size() > 3)
{
- string msg = "sendmultisig <fromaccount> <type> <[\"key\",\"key\"]> <amount> [minconf=1] [comment] [comment-to]\n"
- "<type> is one of: \"and\", \"or\", \"escrow\"\n"
- "<keys> is an array of strings (in JSON array format); each key is a bitcoin address, hex or base58 public key\n"
- "<amount> is a real and is rounded to the nearest 0.00000001";
- if (pwalletMain->IsCrypted())
- msg += "\nrequires wallet passphrase to be set with walletpassphrase first";
+ string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
+ "Add a nrequired-to-sign multisignature address to the wallet\"\n"
+ "each key is a bitcoin address, hex or base58 public key\n"
+ "If [account] is specified, assign address to [account].";
throw runtime_error(msg);
}
- string strAccount = AccountFromValue(params[0]);
- string strType = params[1].get_str();
- const Array& keys = params[2].get_array();
- int64 nAmount = AmountFromValue(params[3]);
- int nMinDepth = 1;
- if (params.size() > 4)
- nMinDepth = params[4].get_int();
-
- CWalletTx wtx;
- wtx.strFromAccount = strAccount;
- if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
- wtx.mapValue["comment"] = params[5].get_str();
- if (params.size() > 6 && params[6].type() != null_type && !params[6].get_str().empty())
- wtx.mapValue["to"] = params[6].get_str();
-
- if (pwalletMain->IsLocked())
- throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
-
- // Check funds
- int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
- if (nAmount > nBalance)
- throw JSONRPCError(-6, "Account has insufficient funds");
+ int nRequired = params[0].get_int();
+ const Array& keys = params[1].get_array();
+ string strAccount;
+ if (params.size() > 2)
+ strAccount = AccountFromValue(params[2]);
// Gather public keys
- int nKeysNeeded = 0;
- if (strType == "and" || strType == "or")
- nKeysNeeded = 2;
- else if (strType == "escrow")
- nKeysNeeded = 3;
- else
- throw runtime_error("sendmultisig: <type> must be one of: and or and_or");
- if (keys.size() != nKeysNeeded)
+ if (keys.size() < nRequired)
throw runtime_error(
- strprintf("sendmultisig: wrong number of keys (got %d, need %d)", keys.size(), nKeysNeeded));
+ strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
std::vector<CKey> pubkeys;
- pubkeys.resize(nKeysNeeded);
- for (int i = 0; i < nKeysNeeded; i++)
+ pubkeys.resize(keys.size());
+ for (int i = 0; i < keys.size(); i++)
{
const std::string& ks = keys[i].get_str();
if (ks.size() == 130) // hex public key
@@ -1003,32 +977,23 @@ Value sendmultisig(const Array& params, bool fHelp)
CBitcoinAddress address(ks);
if (!pwalletMain->GetKey(address, pubkeys[i]))
throw runtime_error(
- strprintf("sendmultisig: unknown address: %s",ks.c_str()));
+ strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
}
}
- // Send
- CScript scriptPubKey;
- if (strType == "and")
- scriptPubKey.SetMultisigAnd(pubkeys);
- else if (strType == "or")
- scriptPubKey.SetMultisigOr(pubkeys);
- else
- scriptPubKey.SetMultisigEscrow(pubkeys);
+ // Construct using OP_EVAL
+ CScript inner;
+ inner.SetMultisig(nRequired, pubkeys);
- CReserveKey keyChange(pwalletMain);
- int64 nFeeRequired = 0;
- bool fCreated = pwalletMain->CreateTransaction(scriptPubKey, nAmount, wtx, keyChange, nFeeRequired);
- if (!fCreated)
- {
- if (nAmount + nFeeRequired > pwalletMain->GetBalance())
- throw JSONRPCError(-6, "Insufficient funds");
- throw JSONRPCError(-4, "Transaction creation failed");
- }
- if (!pwalletMain->CommitTransaction(wtx, keyChange))
- throw JSONRPCError(-4, "Transaction commit failed");
+ uint160 scriptHash = Hash160(inner);
+ CScript scriptPubKey;
+ scriptPubKey.SetEval(inner);
+ pwalletMain->AddCScript(scriptHash, inner);
+ CBitcoinAddress address;
+ address.SetScriptHash160(scriptHash);
- return wtx.GetHash().GetHex();
+ pwalletMain->SetAddressBookName(address, strAccount);
+ return address.ToString();
}
@@ -1700,6 +1665,24 @@ Value validateaddress(const Array& params, bool fHelp)
std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
}
+ else if (pwalletMain->HaveCScript(address.GetHash160()))
+ {
+ ret.push_back(Pair("isscript", true));
+ CScript subscript;
+ pwalletMain->GetCScript(address.GetHash160(), subscript);
+ ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
+ std::vector<CBitcoinAddress> addresses;
+ txntype whichType;
+ int nRequired;
+ ExtractAddresses(subscript, pwalletMain, whichType, addresses, nRequired);
+ ret.push_back(Pair("script", GetTxnTypeName(whichType)));
+ Array a;
+ BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
+ a.push_back(addr.ToString());
+ ret.push_back(Pair("addresses", a));
+ if (whichType == TX_MULTISIG)
+ ret.push_back(Pair("sigsrequired", nRequired));
+ }
else
ret.push_back(Pair("ismine", false));
if (pwalletMain->mapAddressBook.count(address))
@@ -1946,7 +1929,7 @@ pair<string, rpcfn_type> pCallTable[] =
make_pair("move", &movecmd),
make_pair("sendfrom", &sendfrom),
make_pair("sendmany", &sendmany),
- make_pair("sendmultisig", &sendmultisig),
+ make_pair("addmultisigaddress", &addmultisigaddress),
make_pair("gettransaction", &gettransaction),
make_pair("listtransactions", &listtransactions),
make_pair("signmessage", &signmessage),
@@ -2590,16 +2573,15 @@ int CommandLineRPC(int argc, char *argv[])
params[1] = v.get_obj();
}
if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
- if (strMethod == "sendmultisig" && n > 2)
+ if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "addmultisigaddress" && n > 1)
{
- string s = params[2].get_str();
+ string s = params[1].get_str();
Value v;
if (!read_string(s, v) || v.type() != array_type)
- throw runtime_error("sendmultisig: type mismatch "+s);
- params[2] = v.get_array();
+ throw runtime_error("addmultisigaddress: type mismatch "+s);
+ params[1] = v.get_array();
}
- if (strMethod == "sendmultisig" && n > 3) ConvertTo<double>(params[3]);
- if (strMethod == "sendmultisig" && n > 4) ConvertTo<boost::int64_t>(params[4]);
// Execute
Object reply = CallRPC(strMethod, params);