SRoulette (OP)
|
|
October 11, 2012, 01:50:13 AM Last edit: October 11, 2012, 02:13:13 AM by SRoulette |
|
Poll is running for 2 weeks.
Just trying to gauge interest. We would add PPC support to all our games (Roulette, Dice, SicBo).
edit: for the nay-sayers, back up your position please. Why shouldnt PPC gain extra support ? Id like to hear your thoughts.
|
|
|
|
SRoulette (OP)
|
|
October 11, 2012, 03:49:58 AM |
|
2 people interested so far
|
|
|
|
Liquid
|
|
October 11, 2012, 06:42:15 AM |
|
Go for it
|
Bitcoin will show the world what hard money really is.
|
|
|
MaximousDarwin
Newbie
Offline
Activity: 14
Merit: 0
|
|
October 11, 2012, 10:57:22 AM |
|
It's a great idea. Since PPC has a lower value that would allow users to make lower risk bets
|
|
|
|
AndyRossy
|
|
October 11, 2012, 11:42:34 AM |
|
I think it's a good idea, I cant think of a valid reason why not.
|
|
|
|
peepee
|
|
October 11, 2012, 12:48:10 PM |
|
It would be the first thing I would get to spend PPC on.
Take my money!
|
|
|
|
SRoulette (OP)
|
|
October 11, 2012, 05:31:54 PM |
|
Well I have heard enough, if our spindle disk array can handle one more *coind running that is , SSD raid server upgrade coming soon to alleviate this Which game would you like to see supported first ? What minimum and maximum bets would you like to see ? Is there any issues sending micro payments the size of 0.00000XXX to 0.0000000X ? This Weekend if not sooner you shall have PPC gambling !
|
|
|
|
Sunny King
Legendary
Offline
Activity: 1205
Merit: 1010
|
|
October 11, 2012, 06:55:44 PM |
|
Is there any issues sending micro payments the size of 0.00000XXX to 0.0000000X ?
There is a minimum payment amount built into ppcoind at 1 cent. Minimum transaction fee is at 1 cent as well.
|
|
|
|
dreamwatcher
Legendary
Offline
Activity: 1064
Merit: 1000
|
|
October 11, 2012, 07:20:43 PM |
|
Dammit, this was on my TODO list Oh well, guess I really would not have the time considering the project I am working on now for PPC. I always liked the Roulette game and Dice is just a classic. I would say start with those two. I would say bet ranges should be the PPC value equivalent of BTC bet ranges.
|
|
|
|
SRoulette (OP)
|
|
October 12, 2012, 04:16:39 AM |
|
Dammit, this was on my TODO list Oh well, guess I really would not have the time considering the project I am working on now for PPC. I always liked the Roulette game and Dice is just a classic. I would say start with those two. I would say bet ranges should be the PPC value equivalent of BTC bet ranges. What project are you working on out of interest ?
|
|
|
|
Liquid
|
|
October 12, 2012, 05:00:55 AM |
|
This Weekend if not sooner you shall have PPC gambling !Sweet
|
Bitcoin will show the world what hard money really is.
|
|
|
Ryland R. Taylor-Almanza
Legendary
Offline
Activity: 882
Merit: 1001
|
|
October 12, 2012, 05:16:00 AM |
|
I hope no one votes for namecoin. I actually LIKE namecoin, but I don't think it should be used like any old currency. I believe that people using it as currency is part of the reason it is failing as a datastore system.
|
|
|
|
.BITSLER. | ▄███ ▄████▀ ▄████▀ ▄████▀ ▄██▄ ▄████▀ ▀████▄ ▄████▀ ▀████▄ ▄████▀ ▀████▄ ▄████▀ ▀████▄ ▄████▀ ▄████▄ ▄████▄ ▀████▄ █████ ██████ ██████ █████ ▀████▄ ▀████▀ ▀████▀ ▄████▀ ▀████▄ ▄████▀ ▀████▄ ▄████▀ ▀████▄ ▄████▀ ▀████▄ ▄████▀ ▀████▄▄████▀ ▀██████▀ ▀▀▀▀ | | ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▄ ▄▄▄▄▀▀▀▀ ▄▄█▄▄ ▀▀▄ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▄ █ ▀▄▄ ▀█▀▀ ▄ ▀████ ▀▀▄ █ █▄ ▀▄ ▀████ ▀▀ ▄██▄ ▀▀▄ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ █ ▀▀ ▀▄▄ ▀████ ▄▄▄▀▀▀ █ █ ▄ ▀▄ ▄▄▄▀▀▀ ▄▄ █ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ █ ▄▄ ███ ▀██ █ ▀▀ █ █ ███ ▀██ █ ▄▄ █ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀▄ █ ▀▀ █ ▀▀▄ ███▄ █ ▄▄ █ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀▀▄ █ ▀▀▄▄▄▀▀▀ ▄▄▄▄▄▄▄▄▄▄▄█▄▄▀▀▀▀ | | | | ▄▄▄██████▄▄▄ ▄▄████████████████▄▄ ▄██████▀▀▀▀▀▀▀▀▀▀██████▄ ▄ ▄█████▀ ▀█████▄ ██▄▄ █████▀ ▄ ▀█████ ████████ ▄██ █████ ████████▄ ███▀ ████▄ █████████▀▀ ▄███▀ █████ █▀▀▀ █████ █████ ▄▄▄ ████ █████ █████ ▀▀ ████▀ █████ █████ █████▄ ▄█████ ▀█████▄ ▄█████▀ ▀██████▄▄▄▄▄▄▄▄▄▄██████▀ ▀▀████████████████▀▀ ▀▀▀██████▀▀▀ | | | | ▄▄▄███████▄▄▄ ▄█▀▀▀ ▄▄▄▄▄▄▄ ▀▀▀█▄ █▀▀ ▄█████████████▄ ▀▀█ █▀▀ ███████████████████ ▀▀█ █▀ ███████████████████████ ▀█ █▀ ███████████████▀▀ ███████ ▀█ ▄█▀ ██████████████▀ ▀█████ ▀█▄ ███ ███████████▀▀ ▀▀██ ███ ███ ███████▀▀ ███ ███ ▀▀▀▀ ███ ▀██▄ ▄██▀ ▀█▄ ▀▀ █▄ █▄▄▄▄▄▄▄▄▄█ █▄ ▀█████████▀ ▀█▄ ▀▀▀▀▀▀▀ ▀▀█▄▄ ▄▄▄ ▀▀█████ | | | [ | | ] |
|
|
|
SRoulette (OP)
|
|
October 12, 2012, 05:37:11 PM |
|
Code Monkey: unfortunately the current version of ppcoind does not support the rpc command getrawtranasction As has been explained to me, with that feature missing we cannot support ppcoin at this time with our engine, but we now have games and ppcoins ready for when it is supported.
|
|
|
|
AndyRossy
|
|
October 12, 2012, 05:42:18 PM |
|
Code Monkey: unfortunately the current version of ppcoind does not support the rpc command getrawtranasction As has been explained to me, with that feature missing we cannot support ppcoin at this time with our engine, but we now have games and ppcoins ready for when it is supported. Hi Here's a patch for getrawtransaction. Next release will be forked from bitcoin 0.7.0 as I understand so no patch will be required. Andy diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 3c39a30..adaedae 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -21,7 +21,7 @@ #include <boost/iostreams/stream.hpp> #include <boost/algorithm/string.hpp> #include <boost/lexical_cast.hpp> -#include <boost/asio/ssl.hpp> +#include <boost/asio/ssl.hpp> #include <boost/filesystem/fstream.hpp> typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream; @@ -113,6 +113,33 @@ HexBits(unsigned int nBits) return HexStr(BEGIN(uBits.cBits), END(uBits.cBits)); } +void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out) +{ + txnouttype type; + //vector<CTxDestination> addresses; + vector<CBitcoinAddress> addresses; + int nRequired; + + out.push_back(Pair("asm", scriptPubKey.ToString())); + out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); + + ExtractAddresses(scriptPubKey, type, addresses, nRequired); + /**if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) + { + out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD))); + return; + }**/ + + out.push_back(Pair("reqSigs", nRequired)); + out.push_back(Pair("type", GetTxnOutputType(type))); + + Array a; + BOOST_FOREACH(const CBitcoinAddress& addr, addresses) + a.push_back(addr.ToString()); + out.push_back(Pair("addresses", a)); + +} + void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { int confirms = wtx.GetDepthInMainChain(); @@ -172,6 +199,63 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPri return result; } +void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) +{ + entry.push_back(Pair("txid", tx.GetHash().GetHex())); + entry.push_back(Pair("version", tx.nVersion)); + entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime)); + Array vin; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + Object in; + if (tx.IsCoinBase()) + in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + else + { + in.push_back(Pair("txid", txin.prevout.hash.GetHex())); + in.push_back(Pair("vout", (boost::int64_t)txin.prevout.n)); + Object o; + o.push_back(Pair("asm", txin.scriptSig.ToString())); + o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + in.push_back(Pair("scriptSig", o)); + } + in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence)); + vin.push_back(in); + } + entry.push_back(Pair("vin", vin)); + Array vout; + for (unsigned int i = 0; i < tx.vout.size(); i++) + { + const CTxOut& txout = tx.vout[i]; + Object out; + out.push_back(Pair("value", ValueFromAmount(txout.nValue))); + out.push_back(Pair("n", (boost::int64_t)i)); + Object o; + ScriptPubKeyToJSON(txout.scriptPubKey, o); + out.push_back(Pair("scriptPubKey", o)); + vout.push_back(out); + } + entry.push_back(Pair("vout", vout)); + + if (hashBlock != 0) + { + entry.push_back(Pair("blockhash", hashBlock.GetHex())); + map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pindex = (*mi).second; + if (pindex->IsInMainChain()) + { + entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight)); + entry.push_back(Pair("time", (boost::int64_t)pindex->nTime)); + entry.push_back(Pair("blocktime", (boost::int64_t)pindex->nTime)); + } + else + entry.push_back(Pair("confirmations", 0)); + } + } + } + /// @@ -425,6 +509,133 @@ Value getnewaddress(const Array& params, bool fHelp) } +Value getrawtransaction(const Array& params, bool fHelp) { + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getrawtransaction <txid> [verbose=0]\n" + "If verbose=0, returns a string that is " + "serialized, hex-encoded data for <txid>. " + "If verbose is non-zero, returns an Object " + "with information about <txid>."); + + uint256 hash; + hash.SetHex(params[0].get_str()); + bool fVerbose = false; + if (params.size() > 1) fVerbose = (params[1].get_int() != 0); + + CTransaction tx; + uint256 hashBlock = 0; //Block which contained the tx. + if (!GetTransaction(hash, tx, hashBlock)) + throw JSONRPCError(-5, "No information available about transaction"); + + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << tx; + string strHex = HexStr(ssTx.begin(), ssTx.end()); + + if (!fVerbose) + return strHex; + + Object result; + result.push_back(Pair("hex", strHex)); + //TxToJSON(tx, hashBlock, result); + return result; +} + +Value listunspent(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 3) + throw runtime_error( + "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n" + "Returns array of unspent transaction outputs\n" + "with between minconf and maxconf (inclusive) confirmations.\n" + "Optionally filtered to only include txouts paid to specified addresses.\n" + "Results are an array of Objects, each of which has:\n" + "{txid, vout, scriptPubKey, amount, confirmations}"); + + Object result; + return result; +} + +Value createrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...}\n" + "Create a transaction spending given inputs\n" + "(array of objects containing transaction id and output number),\n" + "sending to given address(es).\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."); + + Object result; + return result; +} + +Value signrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 4) + throw runtime_error( + "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n" + "Sign inputs for raw transaction (serialized, hex-encoded).\n" + "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 blockchain.\n" + "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" + "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n" + "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n" + "Returns json object with keys:\n" + " hex : raw transaction with signature(s) (hex-encoded string)\n" + " complete : 1 if transaction has a complete set of signature (0 if not)" + "UPDATE ME"); + + + Object result; + + return result; +} + +Value sendrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1) + throw runtime_error( + "sendrawtransaction <hex string>\n" + "Submits raw transaction (serialized, hex-encoded) to local node and network."); + Object result; + + return result; +} + +Value decoderawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "decoderawtransaction <hex string>\n" + "Return a JSON object representing the serialized, hex-encoded transaction."); + //RPCTypeCheck(params, list_of(str_type)); + + vector<unsigned char> txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + try { + ssData >> tx; + } + catch (std::exception &e) { + throw JSONRPCError(-22, "TX decode failed"); + } + + Object result; + TxToJSON(tx, 0, result); + + return result; + + +} + + + + + CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) { CWalletDB walletdb(pwalletMain->strWalletFile); @@ -976,7 +1187,7 @@ Value sendmany(const Array& params, bool fHelp) CScript scriptPubKey; scriptPubKey.SetBitcoinAddress(address); - int64 nAmount = AmountFromValue(s.value_); + int64 nAmount = AmountFromValue(s.value_); if (nAmount < MIN_TXOUT_AMOUNT) throw JSONRPCError(-101, "Send amount too small"); totalAmount += nAmount; @@ -1361,7 +1572,7 @@ Value listtransactions(const Array& params, bool fHelp) if (ret.size() >= (nCount+nFrom)) break; } // ret is newest to oldest - + if (nFrom > (int)ret.size()) nFrom = ret.size(); if ((nFrom + nCount) > (int)ret.size()) @@ -2043,9 +2254,9 @@ Value getcheckpoint(const Array& params, bool fHelp) Object result; CBlockIndex* pindexCheckpoint; - + result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str())); - pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; + pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); if (mapArgs.count("-checkpointkey")) @@ -2154,7 +2365,7 @@ Value makekeypair(const Array& params, bool fHelp) string strPrefix = ""; if (params.size() > 0) strPrefix = params[0].get_str(); - + CKey key; int nCount = 0; do @@ -2176,7 +2387,7 @@ Value makekeypair(const Array& params, bool fHelp) extern CCriticalSection cs_mapAlerts; extern map<uint256, CAlert> mapAlerts; -// ppcoin: send alert. +// ppcoin: send alert. // There is a known deadlock situation with ThreadMessageHandler // ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages() // ThreadRPCServer: holds cs_main and acquiring cs_vSend in alert.RelayTo()/PushMessage()/BeginMessage() @@ -2211,13 +2422,13 @@ Value sendalert(const Array& params, bool fHelp) CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); sMsg << (CUnsignedAlert)alert; alert.vchMsg = vector<unsigned char>(sMsg.begin(), sMsg.end()); - + vector<unsigned char> vchPrivKey = ParseHex(params[1].get_str()); key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) throw runtime_error( - "Unable to sign alert, check private key?\n"); - if(!alert.ProcessAlert()) + "Unable to sign alert, check private key?\n"); + if(!alert.ProcessAlert()) throw runtime_error( "Failed to process alert.\n"); // Relay alert @@ -2301,6 +2512,12 @@ static const CRPCCommand vRPCCommands[] = { "repairwallet", &repairwallet, false}, { "makekeypair", &makekeypair, false}, { "sendalert", &sendalert, false}, + { "getrawtransaction", &getrawtransaction, false}, + { "listunspent", &listunspent, false}, + { "createrawtransaction", &createrawtransaction, false}, + { "signrawtransaction", &signrawtransaction, false}, + { "sendrawtransaction", &sendrawtransaction, false}, + { "decoderawtransaction", &decoderawtransaction, false}, }; CRPCTable::CRPCTable() @@ -2849,15 +3066,19 @@ Object CallRPC(const string& strMethod, const Array& params) template<typename T> -void ConvertTo(Value& value) +void ConvertTo(Value& value, bool fAllowNull=false) { + if (fAllowNull && value.type() == null_type) + return; if (value.type() == str_type) { // reinterpret string as unquoted json value Value value2; - if (!read_string(value.get_str(), value2)) - throw runtime_error("type mismatch"); - value = value2.get_value<T>(); + string strJSON = value.get_str(); + if (!read_string(strJSON, value2)) + throw runtime_error(string("Error parsing JSON:")+strJSON); + ConvertTo<T>(value2, fAllowNull); + value = value2; } else { @@ -2940,6 +3161,15 @@ int CommandLineRPC(int argc, char *argv[]) throw runtime_error("type mismatch "+s); params[1] = v.get_array(); } + if (strMethod == "listunspent" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]); + if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]); + if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]); + if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true); + if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true); + // Execute Object reply = CallRPC(strMethod, params); diff --git a/src/main.cpp b/src/main.cpp index a419f7f..6f0603d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -133,6 +133,33 @@ void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate); } +// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock) +{ + { + LOCK(cs_main); + { + LOCK(mempool.cs); + if (mempool.exists(hash)) + { + tx = mempool.lookup(hash); + return true; + } + } + CTxDB txdb("r"); + CTxIndex txindex; + if (tx.ReadFromDisk(txdb, COutPoint(hash, 0), txindex)) + { + CBlock block; + if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + hashBlock = block.GetHash(); + return true; + } + } + return false; +} + + // notify wallets about a new best chain void static SetBestChain(const CBlockLocator& loc) { @@ -1683,7 +1710,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) // more difficult // txPrev.block.nTime: prevent nodes from guessing a good timestamp to // generate transaction for future advantage -// txPrev.offset: offset of txPrev inside block, to reduce the chance of +// txPrev.offset: offset of txPrev inside block, to reduce the chance of // nodes generating coinstake at the same time // txPrev.nTime: reduce the chance of nodes generating coinstake at the same // time @@ -1697,7 +1724,7 @@ bool CTransaction::CheckProofOfStake(unsigned int nBits) const { CBigNum bnTargetPerCoinDay; bnTargetPerCoinDay.SetCompact(nBits); - + if (!IsCoinStake()) return true; @@ -1739,7 +1766,7 @@ bool CTransaction::CheckProofOfStake(unsigned int nBits) const // ppcoin: total coin age spent in transaction, in the unit of coin-days. // Only those coins meeting minimum age requirement counts. As those // transactions not in main chain are not currently indexed so we -// might not find out about their coin age. Older transactions are +// might not find out about their coin age. Older transactions are // guaranteed to be in main chain by sync-checkpoint. This rule is // introduced to help nodes establish a consistent view of the coin // age (trust score) of competing branches. @@ -1817,7 +1844,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) if (!pindexNew) return error("AddToBlockIndex() : new CBlockIndex failed"); map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; - if (pindexNew->fProofOfStake) + if (pindexNew->fProofOfStake) setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime)); pindexNew->phashBlock = &((*mi).first); @@ -1910,7 +1937,7 @@ bool CBlock::CheckBlock() const // Check coinbase reward if (vtx[0].GetValueOut() > (IsProofOfWork()? (GetProofOfWorkReward(nBits) - vtx[0].GetMinFee() + MIN_TX_FEE) : 0)) - return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", + return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", FormatMoney(vtx[0].GetValueOut()).c_str(), FormatMoney(IsProofOfWork()? GetProofOfWorkReward(nBits) : 0).c_str())); @@ -2433,7 +2460,7 @@ void PrintBlockTree() map<uint256, CAlert> mapAlerts; CCriticalSection cs_mapAlerts; -static string strMintMessage = _("Info: Minting suspended due to locked wallet."); +static string strMintMessage = _("Info: Minting suspended due to locked wallet."); static string strMintWarning; string GetWarnings(string strFor) @@ -2882,7 +2909,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // and we want it right after the last block so they don't // wait for other stuff first. // ppcoin: send latest proof-of-work block to allow the - // download node to accept as orphan (proof-of-stake + // download node to accept as orphan (proof-of-stake // block might be rejected by stake connection check) vector<CInv> vInv; vInv.push_back(CInv(MSG_BLOCK, GetLastBlockIndex(pindexBest, false)->GetBlockHash())); @@ -3959,7 +3986,7 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake) continue; } strMintWarning = ""; - printf("CPUMiner : proof-of-stake block found %s\n", pblock->GetHash().ToString().c_str()); + printf("CPUMiner : proof-of-stake block found %s\n", pblock->GetHash().ToString().c_str()); SetThreadPriority(THREAD_PRIORITY_NORMAL); CheckWork(pblock.get(), *pwalletMain, reservekey); SetThreadPriority(THREAD_PRIORITY_LOWEST); diff --git a/src/main.h b/src/main.h index 60e4832..c5ab56d 100644 --- a/src/main.h +++ b/src/main.h @@ -119,8 +119,7 @@ std::string GetWarnings(std::string strFor); uint256 WantedByOrphan(const CBlock* pblockOrphan); const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake); void BitcoinMiner(CWallet *pwallet, bool fProofOfStake); - - +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock); @@ -856,7 +855,7 @@ public: return !(a == b); } int GetDepthInMainChain() const; - + };
|
|
|
|
dreamwatcher
Legendary
Offline
Activity: 1064
Merit: 1000
|
|
October 12, 2012, 05:58:11 PM |
|
Dammit, this was on my TODO list Oh well, guess I really would not have the time considering the project I am working on now for PPC. I always liked the Roulette game and Dice is just a classic. I would say start with those two. I would say bet ranges should be the PPC value equivalent of BTC bet ranges. What project are you working on out of interest ? Everything about my current PPC projects will be in this thread for now: https://bitcointalk.org/index.php?topic=112972.0Once the GUI client hits a stage where it can be beta tested, I will create a new thread for it.
|
|
|
|
SRoulette (OP)
|
|
October 12, 2012, 07:00:50 PM |
|
Code Monkey: unfortunately the current version of ppcoind does not support the rpc command getrawtranasction As has been explained to me, with that feature missing we cannot support ppcoin at this time with our engine, but we now have games and ppcoins ready for when it is supported. Hi Here's a patch for getrawtransaction. Next release will be forked from bitcoin 0.7.0 as I understand so no patch will be required. Andy diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 3c39a30..adaedae 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -21,7 +21,7 @@ #include <boost/iostreams/stream.hpp> #include <boost/algorithm/string.hpp> #include <boost/lexical_cast.hpp> -#include <boost/asio/ssl.hpp> +#include <boost/asio/ssl.hpp> #include <boost/filesystem/fstream.hpp> typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream; @@ -113,6 +113,33 @@ HexBits(unsigned int nBits) return HexStr(BEGIN(uBits.cBits), END(uBits.cBits)); } +void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out) +{ + txnouttype type; + //vector<CTxDestination> addresses; + vector<CBitcoinAddress> addresses; + int nRequired; + + out.push_back(Pair("asm", scriptPubKey.ToString())); + out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); + + ExtractAddresses(scriptPubKey, type, addresses, nRequired); + /**if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) + { + out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD))); + return; + }**/ + + out.push_back(Pair("reqSigs", nRequired)); + out.push_back(Pair("type", GetTxnOutputType(type))); + + Array a; + BOOST_FOREACH(const CBitcoinAddress& addr, addresses) + a.push_back(addr.ToString()); + out.push_back(Pair("addresses", a)); + +} + void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { int confirms = wtx.GetDepthInMainChain(); @@ -172,6 +199,63 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPri return result; } +void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) +{ + entry.push_back(Pair("txid", tx.GetHash().GetHex())); + entry.push_back(Pair("version", tx.nVersion)); + entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime)); + Array vin; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + Object in; + if (tx.IsCoinBase()) + in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + else + { + in.push_back(Pair("txid", txin.prevout.hash.GetHex())); + in.push_back(Pair("vout", (boost::int64_t)txin.prevout.n)); + Object o; + o.push_back(Pair("asm", txin.scriptSig.ToString())); + o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + in.push_back(Pair("scriptSig", o)); + } + in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence)); + vin.push_back(in); + } + entry.push_back(Pair("vin", vin)); + Array vout; + for (unsigned int i = 0; i < tx.vout.size(); i++) + { + const CTxOut& txout = tx.vout[i]; + Object out; + out.push_back(Pair("value", ValueFromAmount(txout.nValue))); + out.push_back(Pair("n", (boost::int64_t)i)); + Object o; + ScriptPubKeyToJSON(txout.scriptPubKey, o); + out.push_back(Pair("scriptPubKey", o)); + vout.push_back(out); + } + entry.push_back(Pair("vout", vout)); + + if (hashBlock != 0) + { + entry.push_back(Pair("blockhash", hashBlock.GetHex())); + map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pindex = (*mi).second; + if (pindex->IsInMainChain()) + { + entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight)); + entry.push_back(Pair("time", (boost::int64_t)pindex->nTime)); + entry.push_back(Pair("blocktime", (boost::int64_t)pindex->nTime)); + } + else + entry.push_back(Pair("confirmations", 0)); + } + } + } + /// @@ -425,6 +509,133 @@ Value getnewaddress(const Array& params, bool fHelp) } +Value getrawtransaction(const Array& params, bool fHelp) { + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getrawtransaction <txid> [verbose=0]\n" + "If verbose=0, returns a string that is " + "serialized, hex-encoded data for <txid>. " + "If verbose is non-zero, returns an Object " + "with information about <txid>."); + + uint256 hash; + hash.SetHex(params[0].get_str()); + bool fVerbose = false; + if (params.size() > 1) fVerbose = (params[1].get_int() != 0); + + CTransaction tx; + uint256 hashBlock = 0; //Block which contained the tx. + if (!GetTransaction(hash, tx, hashBlock)) + throw JSONRPCError(-5, "No information available about transaction"); + + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << tx; + string strHex = HexStr(ssTx.begin(), ssTx.end()); + + if (!fVerbose) + return strHex; + + Object result; + result.push_back(Pair("hex", strHex)); + //TxToJSON(tx, hashBlock, result); + return result; +} + +Value listunspent(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 3) + throw runtime_error( + "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n" + "Returns array of unspent transaction outputs\n" + "with between minconf and maxconf (inclusive) confirmations.\n" + "Optionally filtered to only include txouts paid to specified addresses.\n" + "Results are an array of Objects, each of which has:\n" + "{txid, vout, scriptPubKey, amount, confirmations}"); + + Object result; + return result; +} + +Value createrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...}\n" + "Create a transaction spending given inputs\n" + "(array of objects containing transaction id and output number),\n" + "sending to given address(es).\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."); + + Object result; + return result; +} + +Value signrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 4) + throw runtime_error( + "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n" + "Sign inputs for raw transaction (serialized, hex-encoded).\n" + "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 blockchain.\n" + "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" + "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n" + "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n" + "Returns json object with keys:\n" + " hex : raw transaction with signature(s) (hex-encoded string)\n" + " complete : 1 if transaction has a complete set of signature (0 if not)" + "UPDATE ME"); + + + Object result; + + return result; +} + +Value sendrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1) + throw runtime_error( + "sendrawtransaction <hex string>\n" + "Submits raw transaction (serialized, hex-encoded) to local node and network."); + Object result; + + return result; +} + +Value decoderawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "decoderawtransaction <hex string>\n" + "Return a JSON object representing the serialized, hex-encoded transaction."); + //RPCTypeCheck(params, list_of(str_type)); + + vector<unsigned char> txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + try { + ssData >> tx; + } + catch (std::exception &e) { + throw JSONRPCError(-22, "TX decode failed"); + } + + Object result; + TxToJSON(tx, 0, result); + + return result; + + +} + + + + + CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) { CWalletDB walletdb(pwalletMain->strWalletFile); @@ -976,7 +1187,7 @@ Value sendmany(const Array& params, bool fHelp) CScript scriptPubKey; scriptPubKey.SetBitcoinAddress(address); - int64 nAmount = AmountFromValue(s.value_); + int64 nAmount = AmountFromValue(s.value_); if (nAmount < MIN_TXOUT_AMOUNT) throw JSONRPCError(-101, "Send amount too small"); totalAmount += nAmount; @@ -1361,7 +1572,7 @@ Value listtransactions(const Array& params, bool fHelp) if (ret.size() >= (nCount+nFrom)) break; } // ret is newest to oldest - + if (nFrom > (int)ret.size()) nFrom = ret.size(); if ((nFrom + nCount) > (int)ret.size()) @@ -2043,9 +2254,9 @@ Value getcheckpoint(const Array& params, bool fHelp) Object result; CBlockIndex* pindexCheckpoint; - + result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str())); - pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; + pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); if (mapArgs.count("-checkpointkey")) @@ -2154,7 +2365,7 @@ Value makekeypair(const Array& params, bool fHelp) string strPrefix = ""; if (params.size() > 0) strPrefix = params[0].get_str(); - + CKey key; int nCount = 0; do @@ -2176,7 +2387,7 @@ Value makekeypair(const Array& params, bool fHelp) extern CCriticalSection cs_mapAlerts; extern map<uint256, CAlert> mapAlerts; -// ppcoin: send alert. +// ppcoin: send alert. // There is a known deadlock situation with ThreadMessageHandler // ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages() // ThreadRPCServer: holds cs_main and acquiring cs_vSend in alert.RelayTo()/PushMessage()/BeginMessage() @@ -2211,13 +2422,13 @@ Value sendalert(const Array& params, bool fHelp) CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); sMsg << (CUnsignedAlert)alert; alert.vchMsg = vector<unsigned char>(sMsg.begin(), sMsg.end()); - + vector<unsigned char> vchPrivKey = ParseHex(params[1].get_str()); key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) throw runtime_error( - "Unable to sign alert, check private key?\n"); - if(!alert.ProcessAlert()) + "Unable to sign alert, check private key?\n"); + if(!alert.ProcessAlert()) throw runtime_error( "Failed to process alert.\n"); // Relay alert @@ -2301,6 +2512,12 @@ static const CRPCCommand vRPCCommands[] = { "repairwallet", &repairwallet, false}, { "makekeypair", &makekeypair, false}, { "sendalert", &sendalert, false}, + { "getrawtransaction", &getrawtransaction, false}, + { "listunspent", &listunspent, false}, + { "createrawtransaction", &createrawtransaction, false}, + { "signrawtransaction", &signrawtransaction, false}, + { "sendrawtransaction", &sendrawtransaction, false}, + { "decoderawtransaction", &decoderawtransaction, false}, }; CRPCTable::CRPCTable() @@ -2849,15 +3066,19 @@ Object CallRPC(const string& strMethod, const Array& params) template<typename T> -void ConvertTo(Value& value) +void ConvertTo(Value& value, bool fAllowNull=false) { + if (fAllowNull && value.type() == null_type) + return; if (value.type() == str_type) { // reinterpret string as unquoted json value Value value2; - if (!read_string(value.get_str(), value2)) - throw runtime_error("type mismatch"); - value = value2.get_value<T>(); + string strJSON = value.get_str(); + if (!read_string(strJSON, value2)) + throw runtime_error(string("Error parsing JSON:")+strJSON); + ConvertTo<T>(value2, fAllowNull); + value = value2; } else { @@ -2940,6 +3161,15 @@ int CommandLineRPC(int argc, char *argv[]) throw runtime_error("type mismatch "+s); params[1] = v.get_array(); } + if (strMethod == "listunspent" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]); + if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]); + if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]); + if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true); + if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true); + // Execute Object reply = CallRPC(strMethod, params); diff --git a/src/main.cpp b/src/main.cpp index a419f7f..6f0603d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -133,6 +133,33 @@ void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate); } +// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock) +{ + { + LOCK(cs_main); + { + LOCK(mempool.cs); + if (mempool.exists(hash)) + { + tx = mempool.lookup(hash); + return true; + } + } + CTxDB txdb("r"); + CTxIndex txindex; + if (tx.ReadFromDisk(txdb, COutPoint(hash, 0), txindex)) + { + CBlock block; + if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + hashBlock = block.GetHash(); + return true; + } + } + return false; +} + + // notify wallets about a new best chain void static SetBestChain(const CBlockLocator& loc) { @@ -1683,7 +1710,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) // more difficult // txPrev.block.nTime: prevent nodes from guessing a good timestamp to // generate transaction for future advantage -// txPrev.offset: offset of txPrev inside block, to reduce the chance of +// txPrev.offset: offset of txPrev inside block, to reduce the chance of // nodes generating coinstake at the same time // txPrev.nTime: reduce the chance of nodes generating coinstake at the same // time @@ -1697,7 +1724,7 @@ bool CTransaction::CheckProofOfStake(unsigned int nBits) const { CBigNum bnTargetPerCoinDay; bnTargetPerCoinDay.SetCompact(nBits); - + if (!IsCoinStake()) return true; @@ -1739,7 +1766,7 @@ bool CTransaction::CheckProofOfStake(unsigned int nBits) const // ppcoin: total coin age spent in transaction, in the unit of coin-days. // Only those coins meeting minimum age requirement counts. As those // transactions not in main chain are not currently indexed so we -// might not find out about their coin age. Older transactions are +// might not find out about their coin age. Older transactions are // guaranteed to be in main chain by sync-checkpoint. This rule is // introduced to help nodes establish a consistent view of the coin // age (trust score) of competing branches. @@ -1817,7 +1844,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) if (!pindexNew) return error("AddToBlockIndex() : new CBlockIndex failed"); map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; - if (pindexNew->fProofOfStake) + if (pindexNew->fProofOfStake) setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime)); pindexNew->phashBlock = &((*mi).first); @@ -1910,7 +1937,7 @@ bool CBlock::CheckBlock() const // Check coinbase reward if (vtx[0].GetValueOut() > (IsProofOfWork()? (GetProofOfWorkReward(nBits) - vtx[0].GetMinFee() + MIN_TX_FEE) : 0)) - return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", + return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", FormatMoney(vtx[0].GetValueOut()).c_str(), FormatMoney(IsProofOfWork()? GetProofOfWorkReward(nBits) : 0).c_str())); @@ -2433,7 +2460,7 @@ void PrintBlockTree() map<uint256, CAlert> mapAlerts; CCriticalSection cs_mapAlerts; -static string strMintMessage = _("Info: Minting suspended due to locked wallet."); +static string strMintMessage = _("Info: Minting suspended due to locked wallet."); static string strMintWarning; string GetWarnings(string strFor) @@ -2882,7 +2909,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // and we want it right after the last block so they don't // wait for other stuff first. // ppcoin: send latest proof-of-work block to allow the - // download node to accept as orphan (proof-of-stake + // download node to accept as orphan (proof-of-stake // block might be rejected by stake connection check) vector<CInv> vInv; vInv.push_back(CInv(MSG_BLOCK, GetLastBlockIndex(pindexBest, false)->GetBlockHash())); @@ -3959,7 +3986,7 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake) continue; } strMintWarning = ""; - printf("CPUMiner : proof-of-stake block found %s\n", pblock->GetHash().ToString().c_str()); + printf("CPUMiner : proof-of-stake block found %s\n", pblock->GetHash().ToString().c_str()); SetThreadPriority(THREAD_PRIORITY_NORMAL); CheckWork(pblock.get(), *pwalletMain, reservekey); SetThreadPriority(THREAD_PRIORITY_LOWEST); diff --git a/src/main.h b/src/main.h index 60e4832..c5ab56d 100644 --- a/src/main.h +++ b/src/main.h @@ -119,8 +119,7 @@ std::string GetWarnings(std::string strFor); uint256 WantedByOrphan(const CBlock* pblockOrphan); const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake); void BitcoinMiner(CWallet *pwallet, bool fProofOfStake); - - +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock); @@ -856,7 +855,7 @@ public: return !(a == b); } int GetDepthInMainChain() const; - + }; Codemonkey: Thanks for the patch, we are nearly there. Unfortunately this patch does not send back the verbose output that we use for bitcoind and litecoind. # ~/git/ppcoin/src$ ./ppcoind getrawtransaction 91d2f49cf53a92010bf46428b4d15f21213291a9f37d0cdd9358473abb58629f 1 { "hex" : "01000000b851785001b1e2c809e1783060da96dec47e014273ac3e74d1b353da95f2194165af99b045000000006b483045022100f3d6c5f298b245e07139ac8c9c5aec3e24e0a4ee259675cfb89255c0bc4f637202200ae54063969eb6474b59cff90fe65b5eec8abf75acf08207dcbf7b4eef2426be0121032f9b5ddfc4207549f3c6831edac8e9fa5ad14070a0f2bf958a9f79cddfcd3085ffffffff02d0344a59020000001976a91460a611543f000e04f5a3d44027ef14cc9540316a88ac40420f00000000001976a91449314cc24bbdc74882bcd1180142a584700e036988ac00000000" }
is it possible to enable this ?
|
|
|
|
AndyRossy
|
|
October 12, 2012, 09:18:09 PM |
|
Code Monkey: unfortunately the current version of ppcoind does not support the rpc command getrawtranasction As has been explained to me, with that feature missing we cannot support ppcoin at this time with our engine, but we now have games and ppcoins ready for when it is supported. Hi Here's a patch for getrawtransaction. Next release will be forked from bitcoin 0.7.0 as I understand so no patch will be required. Andy diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 3c39a30..adaedae 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -21,7 +21,7 @@ #include <boost/iostreams/stream.hpp> #include <boost/algorithm/string.hpp> #include <boost/lexical_cast.hpp> -#include <boost/asio/ssl.hpp> +#include <boost/asio/ssl.hpp> #include <boost/filesystem/fstream.hpp> typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream; @@ -113,6 +113,33 @@ HexBits(unsigned int nBits) return HexStr(BEGIN(uBits.cBits), END(uBits.cBits)); } +void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out) +{ + txnouttype type; + //vector<CTxDestination> addresses; + vector<CBitcoinAddress> addresses; + int nRequired; + + out.push_back(Pair("asm", scriptPubKey.ToString())); + out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); + + ExtractAddresses(scriptPubKey, type, addresses, nRequired); + /**if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) + { + out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD))); + return; + }**/ + + out.push_back(Pair("reqSigs", nRequired)); + out.push_back(Pair("type", GetTxnOutputType(type))); + + Array a; + BOOST_FOREACH(const CBitcoinAddress& addr, addresses) + a.push_back(addr.ToString()); + out.push_back(Pair("addresses", a)); + +} + void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { int confirms = wtx.GetDepthInMainChain(); @@ -172,6 +199,63 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPri return result; } +void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) +{ + entry.push_back(Pair("txid", tx.GetHash().GetHex())); + entry.push_back(Pair("version", tx.nVersion)); + entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime)); + Array vin; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + Object in; + if (tx.IsCoinBase()) + in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + else + { + in.push_back(Pair("txid", txin.prevout.hash.GetHex())); + in.push_back(Pair("vout", (boost::int64_t)txin.prevout.n)); + Object o; + o.push_back(Pair("asm", txin.scriptSig.ToString())); + o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + in.push_back(Pair("scriptSig", o)); + } + in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence)); + vin.push_back(in); + } + entry.push_back(Pair("vin", vin)); + Array vout; + for (unsigned int i = 0; i < tx.vout.size(); i++) + { + const CTxOut& txout = tx.vout[i]; + Object out; + out.push_back(Pair("value", ValueFromAmount(txout.nValue))); + out.push_back(Pair("n", (boost::int64_t)i)); + Object o; + ScriptPubKeyToJSON(txout.scriptPubKey, o); + out.push_back(Pair("scriptPubKey", o)); + vout.push_back(out); + } + entry.push_back(Pair("vout", vout)); + + if (hashBlock != 0) + { + entry.push_back(Pair("blockhash", hashBlock.GetHex())); + map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pindex = (*mi).second; + if (pindex->IsInMainChain()) + { + entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight)); + entry.push_back(Pair("time", (boost::int64_t)pindex->nTime)); + entry.push_back(Pair("blocktime", (boost::int64_t)pindex->nTime)); + } + else + entry.push_back(Pair("confirmations", 0)); + } + } + } + /// @@ -425,6 +509,133 @@ Value getnewaddress(const Array& params, bool fHelp) } +Value getrawtransaction(const Array& params, bool fHelp) { + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getrawtransaction <txid> [verbose=0]\n" + "If verbose=0, returns a string that is " + "serialized, hex-encoded data for <txid>. " + "If verbose is non-zero, returns an Object " + "with information about <txid>."); + + uint256 hash; + hash.SetHex(params[0].get_str()); + bool fVerbose = false; + if (params.size() > 1) fVerbose = (params[1].get_int() != 0); + + CTransaction tx; + uint256 hashBlock = 0; //Block which contained the tx. + if (!GetTransaction(hash, tx, hashBlock)) + throw JSONRPCError(-5, "No information available about transaction"); + + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << tx; + string strHex = HexStr(ssTx.begin(), ssTx.end()); + + if (!fVerbose) + return strHex; + + Object result; + result.push_back(Pair("hex", strHex)); + //TxToJSON(tx, hashBlock, result); + return result; +} + +Value listunspent(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 3) + throw runtime_error( + "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n" + "Returns array of unspent transaction outputs\n" + "with between minconf and maxconf (inclusive) confirmations.\n" + "Optionally filtered to only include txouts paid to specified addresses.\n" + "Results are an array of Objects, each of which has:\n" + "{txid, vout, scriptPubKey, amount, confirmations}"); + + Object result; + return result; +} + +Value createrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...}\n" + "Create a transaction spending given inputs\n" + "(array of objects containing transaction id and output number),\n" + "sending to given address(es).\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."); + + Object result; + return result; +} + +Value signrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 4) + throw runtime_error( + "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n" + "Sign inputs for raw transaction (serialized, hex-encoded).\n" + "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 blockchain.\n" + "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" + "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n" + "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n" + "Returns json object with keys:\n" + " hex : raw transaction with signature(s) (hex-encoded string)\n" + " complete : 1 if transaction has a complete set of signature (0 if not)" + "UPDATE ME"); + + + Object result; + + return result; +} + +Value sendrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1) + throw runtime_error( + "sendrawtransaction <hex string>\n" + "Submits raw transaction (serialized, hex-encoded) to local node and network."); + Object result; + + return result; +} + +Value decoderawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "decoderawtransaction <hex string>\n" + "Return a JSON object representing the serialized, hex-encoded transaction."); + //RPCTypeCheck(params, list_of(str_type)); + + vector<unsigned char> txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + try { + ssData >> tx; + } + catch (std::exception &e) { + throw JSONRPCError(-22, "TX decode failed"); + } + + Object result; + TxToJSON(tx, 0, result); + + return result; + + +} + + + + + CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) { CWalletDB walletdb(pwalletMain->strWalletFile); @@ -976,7 +1187,7 @@ Value sendmany(const Array& params, bool fHelp) CScript scriptPubKey; scriptPubKey.SetBitcoinAddress(address); - int64 nAmount = AmountFromValue(s.value_); + int64 nAmount = AmountFromValue(s.value_); if (nAmount < MIN_TXOUT_AMOUNT) throw JSONRPCError(-101, "Send amount too small"); totalAmount += nAmount; @@ -1361,7 +1572,7 @@ Value listtransactions(const Array& params, bool fHelp) if (ret.size() >= (nCount+nFrom)) break; } // ret is newest to oldest - + if (nFrom > (int)ret.size()) nFrom = ret.size(); if ((nFrom + nCount) > (int)ret.size()) @@ -2043,9 +2254,9 @@ Value getcheckpoint(const Array& params, bool fHelp) Object result; CBlockIndex* pindexCheckpoint; - + result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str())); - pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; + pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); if (mapArgs.count("-checkpointkey")) @@ -2154,7 +2365,7 @@ Value makekeypair(const Array& params, bool fHelp) string strPrefix = ""; if (params.size() > 0) strPrefix = params[0].get_str(); - + CKey key; int nCount = 0; do @@ -2176,7 +2387,7 @@ Value makekeypair(const Array& params, bool fHelp) extern CCriticalSection cs_mapAlerts; extern map<uint256, CAlert> mapAlerts; -// ppcoin: send alert. +// ppcoin: send alert. // There is a known deadlock situation with ThreadMessageHandler // ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages() // ThreadRPCServer: holds cs_main and acquiring cs_vSend in alert.RelayTo()/PushMessage()/BeginMessage() @@ -2211,13 +2422,13 @@ Value sendalert(const Array& params, bool fHelp) CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); sMsg << (CUnsignedAlert)alert; alert.vchMsg = vector<unsigned char>(sMsg.begin(), sMsg.end()); - + vector<unsigned char> vchPrivKey = ParseHex(params[1].get_str()); key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) throw runtime_error( - "Unable to sign alert, check private key?\n"); - if(!alert.ProcessAlert()) + "Unable to sign alert, check private key?\n"); + if(!alert.ProcessAlert()) throw runtime_error( "Failed to process alert.\n"); // Relay alert @@ -2301,6 +2512,12 @@ static const CRPCCommand vRPCCommands[] = { "repairwallet", &repairwallet, false}, { "makekeypair", &makekeypair, false}, { "sendalert", &sendalert, false}, + { "getrawtransaction", &getrawtransaction, false}, + { "listunspent", &listunspent, false}, + { "createrawtransaction", &createrawtransaction, false}, + { "signrawtransaction", &signrawtransaction, false}, + { "sendrawtransaction", &sendrawtransaction, false}, + { "decoderawtransaction", &decoderawtransaction, false}, }; CRPCTable::CRPCTable() @@ -2849,15 +3066,19 @@ Object CallRPC(const string& strMethod, const Array& params) template<typename T> -void ConvertTo(Value& value) +void ConvertTo(Value& value, bool fAllowNull=false) { + if (fAllowNull && value.type() == null_type) + return; if (value.type() == str_type) { // reinterpret string as unquoted json value Value value2; - if (!read_string(value.get_str(), value2)) - throw runtime_error("type mismatch"); - value = value2.get_value<T>(); + string strJSON = value.get_str(); + if (!read_string(strJSON, value2)) + throw runtime_error(string("Error parsing JSON:")+strJSON); + ConvertTo<T>(value2, fAllowNull); + value = value2; } else { @@ -2940,6 +3161,15 @@ int CommandLineRPC(int argc, char *argv[]) throw runtime_error("type mismatch "+s); params[1] = v.get_array(); } + if (strMethod == "listunspent" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]); + if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]); + if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]); + if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true); + if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true); + // Execute Object reply = CallRPC(strMethod, params); diff --git a/src/main.cpp b/src/main.cpp index a419f7f..6f0603d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -133,6 +133,33 @@ void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate); } +// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock) +{ + { + LOCK(cs_main); + { + LOCK(mempool.cs); + if (mempool.exists(hash)) + { + tx = mempool.lookup(hash); + return true; + } + } + CTxDB txdb("r"); + CTxIndex txindex; + if (tx.ReadFromDisk(txdb, COutPoint(hash, 0), txindex)) + { + CBlock block; + if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + hashBlock = block.GetHash(); + return true; + } + } + return false; +} + + // notify wallets about a new best chain void static SetBestChain(const CBlockLocator& loc) { @@ -1683,7 +1710,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) // more difficult // txPrev.block.nTime: prevent nodes from guessing a good timestamp to // generate transaction for future advantage -// txPrev.offset: offset of txPrev inside block, to reduce the chance of +// txPrev.offset: offset of txPrev inside block, to reduce the chance of // nodes generating coinstake at the same time // txPrev.nTime: reduce the chance of nodes generating coinstake at the same // time @@ -1697,7 +1724,7 @@ bool CTransaction::CheckProofOfStake(unsigned int nBits) const { CBigNum bnTargetPerCoinDay; bnTargetPerCoinDay.SetCompact(nBits); - + if (!IsCoinStake()) return true; @@ -1739,7 +1766,7 @@ bool CTransaction::CheckProofOfStake(unsigned int nBits) const // ppcoin: total coin age spent in transaction, in the unit of coin-days. // Only those coins meeting minimum age requirement counts. As those // transactions not in main chain are not currently indexed so we -// might not find out about their coin age. Older transactions are +// might not find out about their coin age. Older transactions are // guaranteed to be in main chain by sync-checkpoint. This rule is // introduced to help nodes establish a consistent view of the coin // age (trust score) of competing branches. @@ -1817,7 +1844,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) if (!pindexNew) return error("AddToBlockIndex() : new CBlockIndex failed"); map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; - if (pindexNew->fProofOfStake) + if (pindexNew->fProofOfStake) setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime)); pindexNew->phashBlock = &((*mi).first); @@ -1910,7 +1937,7 @@ bool CBlock::CheckBlock() const // Check coinbase reward if (vtx[0].GetValueOut() > (IsProofOfWork()? (GetProofOfWorkReward(nBits) - vtx[0].GetMinFee() + MIN_TX_FEE) : 0)) - return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", + return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", FormatMoney(vtx[0].GetValueOut()).c_str(), FormatMoney(IsProofOfWork()? GetProofOfWorkReward(nBits) : 0).c_str())); @@ -2433,7 +2460,7 @@ void PrintBlockTree() map<uint256, CAlert> mapAlerts; CCriticalSection cs_mapAlerts; -static string strMintMessage = _("Info: Minting suspended due to locked wallet."); +static string strMintMessage = _("Info: Minting suspended due to locked wallet."); static string strMintWarning; string GetWarnings(string strFor) @@ -2882,7 +2909,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // and we want it right after the last block so they don't // wait for other stuff first. // ppcoin: send latest proof-of-work block to allow the - // download node to accept as orphan (proof-of-stake + // download node to accept as orphan (proof-of-stake // block might be rejected by stake connection check) vector<CInv> vInv; vInv.push_back(CInv(MSG_BLOCK, GetLastBlockIndex(pindexBest, false)->GetBlockHash())); @@ -3959,7 +3986,7 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake) continue; } strMintWarning = ""; - printf("CPUMiner : proof-of-stake block found %s\n", pblock->GetHash().ToString().c_str()); + printf("CPUMiner : proof-of-stake block found %s\n", pblock->GetHash().ToString().c_str()); SetThreadPriority(THREAD_PRIORITY_NORMAL); CheckWork(pblock.get(), *pwalletMain, reservekey); SetThreadPriority(THREAD_PRIORITY_LOWEST); diff --git a/src/main.h b/src/main.h index 60e4832..c5ab56d 100644 --- a/src/main.h +++ b/src/main.h @@ -119,8 +119,7 @@ std::string GetWarnings(std::string strFor); uint256 WantedByOrphan(const CBlock* pblockOrphan); const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake); void BitcoinMiner(CWallet *pwallet, bool fProofOfStake); - - +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock); @@ -856,7 +855,7 @@ public: return !(a == b); } int GetDepthInMainChain() const; - + }; Codemonkey: Thanks for the patch, we are nearly there. Unfortunately this patch does not send back the verbose output that we use for bitcoind and litecoind. # ~/git/ppcoin/src$ ./ppcoind getrawtransaction 91d2f49cf53a92010bf46428b4d15f21213291a9f37d0cdd9358473abb58629f 1 { "hex" : "01000000b851785001b1e2c809e1783060da96dec47e014273ac3e74d1b353da95f2194165af99b045000000006b483045022100f3d6c5f298b245e07139ac8c9c5aec3e24e0a4ee259675cfb89255c0bc4f637202200ae54063969eb6474b59cff90fe65b5eec8abf75acf08207dcbf7b4eef2426be0121032f9b5ddfc4207549f3c6831edac8e9fa5ad14070a0f2bf958a9f79cddfcd3085ffffffff02d0344a59020000001976a91460a611543f000e04f5a3d44027ef14cc9540316a88ac40420f00000000001976a91449314cc24bbdc74882bcd1180142a584700e036988ac00000000" }
is it possible to enable this ? Aha, I can have a look but wont be until Monday, let me exact what idm making a patch if it's relatively simple (sounds like it is). What exactly do you mean? You've looked at decoderawtransaction right?
|
|
|
|
crazy_rabbit
Legendary
Offline
Activity: 1204
Merit: 1002
RUM AND CARROTS: A PIRATE LIFE FOR ME
|
|
October 13, 2012, 12:53:07 AM |
|
personally I hope not, but what the heck.
|
more or less retired.
|
|
|
SRoulette (OP)
|
|
October 13, 2012, 03:32:50 AM |
|
Code Monkey: unfortunately the current version of ppcoind does not support the rpc command getrawtranasction As has been explained to me, with that feature missing we cannot support ppcoin at this time with our engine, but we now have games and ppcoins ready for when it is supported. Hi Here's a patch for getrawtransaction. Next release will be forked from bitcoin 0.7.0 as I understand so no patch will be required. Andy diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 3c39a30..adaedae 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -21,7 +21,7 @@ #include <boost/iostreams/stream.hpp> #include <boost/algorithm/string.hpp> #include <boost/lexical_cast.hpp> -#include <boost/asio/ssl.hpp> +#include <boost/asio/ssl.hpp> #include <boost/filesystem/fstream.hpp> typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream; @@ -113,6 +113,33 @@ HexBits(unsigned int nBits) return HexStr(BEGIN(uBits.cBits), END(uBits.cBits)); } +void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out) +{ + txnouttype type; + //vector<CTxDestination> addresses; + vector<CBitcoinAddress> addresses; + int nRequired; + + out.push_back(Pair("asm", scriptPubKey.ToString())); + out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); + + ExtractAddresses(scriptPubKey, type, addresses, nRequired); + /**if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) + { + out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD))); + return; + }**/ + + out.push_back(Pair("reqSigs", nRequired)); + out.push_back(Pair("type", GetTxnOutputType(type))); + + Array a; + BOOST_FOREACH(const CBitcoinAddress& addr, addresses) + a.push_back(addr.ToString()); + out.push_back(Pair("addresses", a)); + +} + void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { int confirms = wtx.GetDepthInMainChain(); @@ -172,6 +199,63 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPri return result; } +void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) +{ + entry.push_back(Pair("txid", tx.GetHash().GetHex())); + entry.push_back(Pair("version", tx.nVersion)); + entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime)); + Array vin; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + Object in; + if (tx.IsCoinBase()) + in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + else + { + in.push_back(Pair("txid", txin.prevout.hash.GetHex())); + in.push_back(Pair("vout", (boost::int64_t)txin.prevout.n)); + Object o; + o.push_back(Pair("asm", txin.scriptSig.ToString())); + o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + in.push_back(Pair("scriptSig", o)); + } + in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence)); + vin.push_back(in); + } + entry.push_back(Pair("vin", vin)); + Array vout; + for (unsigned int i = 0; i < tx.vout.size(); i++) + { + const CTxOut& txout = tx.vout[i]; + Object out; + out.push_back(Pair("value", ValueFromAmount(txout.nValue))); + out.push_back(Pair("n", (boost::int64_t)i)); + Object o; + ScriptPubKeyToJSON(txout.scriptPubKey, o); + out.push_back(Pair("scriptPubKey", o)); + vout.push_back(out); + } + entry.push_back(Pair("vout", vout)); + + if (hashBlock != 0) + { + entry.push_back(Pair("blockhash", hashBlock.GetHex())); + map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pindex = (*mi).second; + if (pindex->IsInMainChain()) + { + entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight)); + entry.push_back(Pair("time", (boost::int64_t)pindex->nTime)); + entry.push_back(Pair("blocktime", (boost::int64_t)pindex->nTime)); + } + else + entry.push_back(Pair("confirmations", 0)); + } + } + } + /// @@ -425,6 +509,133 @@ Value getnewaddress(const Array& params, bool fHelp) } +Value getrawtransaction(const Array& params, bool fHelp) { + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getrawtransaction <txid> [verbose=0]\n" + "If verbose=0, returns a string that is " + "serialized, hex-encoded data for <txid>. " + "If verbose is non-zero, returns an Object " + "with information about <txid>."); + + uint256 hash; + hash.SetHex(params[0].get_str()); + bool fVerbose = false; + if (params.size() > 1) fVerbose = (params[1].get_int() != 0); + + CTransaction tx; + uint256 hashBlock = 0; //Block which contained the tx. + if (!GetTransaction(hash, tx, hashBlock)) + throw JSONRPCError(-5, "No information available about transaction"); + + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << tx; + string strHex = HexStr(ssTx.begin(), ssTx.end()); + + if (!fVerbose) + return strHex; + + Object result; + result.push_back(Pair("hex", strHex)); + //TxToJSON(tx, hashBlock, result); + return result; +} + +Value listunspent(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 3) + throw runtime_error( + "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n" + "Returns array of unspent transaction outputs\n" + "with between minconf and maxconf (inclusive) confirmations.\n" + "Optionally filtered to only include txouts paid to specified addresses.\n" + "Results are an array of Objects, each of which has:\n" + "{txid, vout, scriptPubKey, amount, confirmations}"); + + Object result; + return result; +} + +Value createrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...}\n" + "Create a transaction spending given inputs\n" + "(array of objects containing transaction id and output number),\n" + "sending to given address(es).\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."); + + Object result; + return result; +} + +Value signrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 4) + throw runtime_error( + "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n" + "Sign inputs for raw transaction (serialized, hex-encoded).\n" + "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 blockchain.\n" + "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" + "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n" + "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n" + "Returns json object with keys:\n" + " hex : raw transaction with signature(s) (hex-encoded string)\n" + " complete : 1 if transaction has a complete set of signature (0 if not)" + "UPDATE ME"); + + + Object result; + + return result; +} + +Value sendrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1) + throw runtime_error( + "sendrawtransaction <hex string>\n" + "Submits raw transaction (serialized, hex-encoded) to local node and network."); + Object result; + + return result; +} + +Value decoderawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "decoderawtransaction <hex string>\n" + "Return a JSON object representing the serialized, hex-encoded transaction."); + //RPCTypeCheck(params, list_of(str_type)); + + vector<unsigned char> txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + try { + ssData >> tx; + } + catch (std::exception &e) { + throw JSONRPCError(-22, "TX decode failed"); + } + + Object result; + TxToJSON(tx, 0, result); + + return result; + + +} + + + + + CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) { CWalletDB walletdb(pwalletMain->strWalletFile); @@ -976,7 +1187,7 @@ Value sendmany(const Array& params, bool fHelp) CScript scriptPubKey; scriptPubKey.SetBitcoinAddress(address); - int64 nAmount = AmountFromValue(s.value_); + int64 nAmount = AmountFromValue(s.value_); if (nAmount < MIN_TXOUT_AMOUNT) throw JSONRPCError(-101, "Send amount too small"); totalAmount += nAmount; @@ -1361,7 +1572,7 @@ Value listtransactions(const Array& params, bool fHelp) if (ret.size() >= (nCount+nFrom)) break; } // ret is newest to oldest - + if (nFrom > (int)ret.size()) nFrom = ret.size(); if ((nFrom + nCount) > (int)ret.size()) @@ -2043,9 +2254,9 @@ Value getcheckpoint(const Array& params, bool fHelp) Object result; CBlockIndex* pindexCheckpoint; - + result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str())); - pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; + pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); if (mapArgs.count("-checkpointkey")) @@ -2154,7 +2365,7 @@ Value makekeypair(const Array& params, bool fHelp) string strPrefix = ""; if (params.size() > 0) strPrefix = params[0].get_str(); - + CKey key; int nCount = 0; do @@ -2176,7 +2387,7 @@ Value makekeypair(const Array& params, bool fHelp) extern CCriticalSection cs_mapAlerts; extern map<uint256, CAlert> mapAlerts; -// ppcoin: send alert. +// ppcoin: send alert. // There is a known deadlock situation with ThreadMessageHandler // ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages() // ThreadRPCServer: holds cs_main and acquiring cs_vSend in alert.RelayTo()/PushMessage()/BeginMessage() @@ -2211,13 +2422,13 @@ Value sendalert(const Array& params, bool fHelp) CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); sMsg << (CUnsignedAlert)alert; alert.vchMsg = vector<unsigned char>(sMsg.begin(), sMsg.end()); - + vector<unsigned char> vchPrivKey = ParseHex(params[1].get_str()); key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) throw runtime_error( - "Unable to sign alert, check private key?\n"); - if(!alert.ProcessAlert()) + "Unable to sign alert, check private key?\n"); + if(!alert.ProcessAlert()) throw runtime_error( "Failed to process alert.\n"); // Relay alert @@ -2301,6 +2512,12 @@ static const CRPCCommand vRPCCommands[] = { "repairwallet", &repairwallet, false}, { "makekeypair", &makekeypair, false}, { "sendalert", &sendalert, false}, + { "getrawtransaction", &getrawtransaction, false}, + { "listunspent", &listunspent, false}, + { "createrawtransaction", &createrawtransaction, false}, + { "signrawtransaction", &signrawtransaction, false}, + { "sendrawtransaction", &sendrawtransaction, false}, + { "decoderawtransaction", &decoderawtransaction, false}, }; CRPCTable::CRPCTable() @@ -2849,15 +3066,19 @@ Object CallRPC(const string& strMethod, const Array& params) template<typename T> -void ConvertTo(Value& value) +void ConvertTo(Value& value, bool fAllowNull=false) { + if (fAllowNull && value.type() == null_type) + return; if (value.type() == str_type) { // reinterpret string as unquoted json value Value value2; - if (!read_string(value.get_str(), value2)) - throw runtime_error("type mismatch"); - value = value2.get_value<T>(); + string strJSON = value.get_str(); + if (!read_string(strJSON, value2)) + throw runtime_error(string("Error parsing JSON:")+strJSON); + ConvertTo<T>(value2, fAllowNull); + value = value2; } else { @@ -2940,6 +3161,15 @@ int CommandLineRPC(int argc, char *argv[]) throw runtime_error("type mismatch "+s); params[1] = v.get_array(); } + if (strMethod == "listunspent" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]); + if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]); + if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]); + if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true); + if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true); + // Execute Object reply = CallRPC(strMethod, params); diff --git a/src/main.cpp b/src/main.cpp index a419f7f..6f0603d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -133,6 +133,33 @@ void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate); } +// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock) +{ + { + LOCK(cs_main); + { + LOCK(mempool.cs); + if (mempool.exists(hash)) + { + tx = mempool.lookup(hash); + return true; + } + } + CTxDB txdb("r"); + CTxIndex txindex; + if (tx.ReadFromDisk(txdb, COutPoint(hash, 0), txindex)) + { + CBlock block; + if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + hashBlock = block.GetHash(); + return true; + } + } + return false; +} + + // notify wallets about a new best chain void static SetBestChain(const CBlockLocator& loc) { @@ -1683,7 +1710,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) // more difficult // txPrev.block.nTime: prevent nodes from guessing a good timestamp to // generate transaction for future advantage -// txPrev.offset: offset of txPrev inside block, to reduce the chance of +// txPrev.offset: offset of txPrev inside block, to reduce the chance of // nodes generating coinstake at the same time // txPrev.nTime: reduce the chance of nodes generating coinstake at the same // time @@ -1697,7 +1724,7 @@ bool CTransaction::CheckProofOfStake(unsigned int nBits) const { CBigNum bnTargetPerCoinDay; bnTargetPerCoinDay.SetCompact(nBits); - + if (!IsCoinStake()) return true; @@ -1739,7 +1766,7 @@ bool CTransaction::CheckProofOfStake(unsigned int nBits) const // ppcoin: total coin age spent in transaction, in the unit of coin-days. // Only those coins meeting minimum age requirement counts. As those // transactions not in main chain are not currently indexed so we -// might not find out about their coin age. Older transactions are +// might not find out about their coin age. Older transactions are // guaranteed to be in main chain by sync-checkpoint. This rule is // introduced to help nodes establish a consistent view of the coin // age (trust score) of competing branches. @@ -1817,7 +1844,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) if (!pindexNew) return error("AddToBlockIndex() : new CBlockIndex failed"); map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; - if (pindexNew->fProofOfStake) + if (pindexNew->fProofOfStake) setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime)); pindexNew->phashBlock = &((*mi).first); @@ -1910,7 +1937,7 @@ bool CBlock::CheckBlock() const // Check coinbase reward if (vtx[0].GetValueOut() > (IsProofOfWork()? (GetProofOfWorkReward(nBits) - vtx[0].GetMinFee() + MIN_TX_FEE) : 0)) - return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", + return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", FormatMoney(vtx[0].GetValueOut()).c_str(), FormatMoney(IsProofOfWork()? GetProofOfWorkReward(nBits) : 0).c_str())); @@ -2433,7 +2460,7 @@ void PrintBlockTree() map<uint256, CAlert> mapAlerts; CCriticalSection cs_mapAlerts; -static string strMintMessage = _("Info: Minting suspended due to locked wallet."); +static string strMintMessage = _("Info: Minting suspended due to locked wallet."); static string strMintWarning; string GetWarnings(string strFor) @@ -2882,7 +2909,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // and we want it right after the last block so they don't // wait for other stuff first. // ppcoin: send latest proof-of-work block to allow the - // download node to accept as orphan (proof-of-stake + // download node to accept as orphan (proof-of-stake // block might be rejected by stake connection check) vector<CInv> vInv; vInv.push_back(CInv(MSG_BLOCK, GetLastBlockIndex(pindexBest, false)->GetBlockHash())); @@ -3959,7 +3986,7 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake) continue; } strMintWarning = ""; - printf("CPUMiner : proof-of-stake block found %s\n", pblock->GetHash().ToString().c_str()); + printf("CPUMiner : proof-of-stake block found %s\n", pblock->GetHash().ToString().c_str()); SetThreadPriority(THREAD_PRIORITY_NORMAL); CheckWork(pblock.get(), *pwalletMain, reservekey); SetThreadPriority(THREAD_PRIORITY_LOWEST); diff --git a/src/main.h b/src/main.h index 60e4832..c5ab56d 100644 --- a/src/main.h +++ b/src/main.h @@ -119,8 +119,7 @@ std::string GetWarnings(std::string strFor); uint256 WantedByOrphan(const CBlock* pblockOrphan); const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake); void BitcoinMiner(CWallet *pwallet, bool fProofOfStake); - - +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock); @@ -856,7 +855,7 @@ public: return !(a == b); } int GetDepthInMainChain() const; - + }; Codemonkey: Thanks for the patch, we are nearly there. Unfortunately this patch does not send back the verbose output that we use for bitcoind and litecoind. # ~/git/ppcoin/src$ ./ppcoind getrawtransaction 91d2f49cf53a92010bf46428b4d15f21213291a9f37d0cdd9358473abb58629f 1 { "hex" : "01000000b851785001b1e2c809e1783060da96dec47e014273ac3e74d1b353da95f2194165af99b045000000006b483045022100f3d6c5f298b245e07139ac8c9c5aec3e24e0a4ee259675cfb89255c0bc4f637202200ae54063969eb6474b59cff90fe65b5eec8abf75acf08207dcbf7b4eef2426be0121032f9b5ddfc4207549f3c6831edac8e9fa5ad14070a0f2bf958a9f79cddfcd3085ffffffff02d0344a59020000001976a91460a611543f000e04f5a3d44027ef14cc9540316a88ac40420f00000000001976a91449314cc24bbdc74882bcd1180142a584700e036988ac00000000" }
is it possible to enable this ? Aha, I can have a look but wont be until Monday, let me exact what idm making a patch if it's relatively simple (sounds like it is). What exactly do you mean? You've looked at decoderawtransaction right? We now use decoderawtransaction as you suggested, just 1 extra step. We have test games up now, but we are finding a few small bugs/ features such as:
We get the above error when trying to send amounts under 1 PPC from our windows 7 test machines, it seems after we see this error on the GUI client it will display it for every transaction even if it is sent.
On our linux server gets a 500 error from RPC when attempting to send amounts under 1 PPC. We had a similar issue with litecoin, to work around this currently payouts under 1 PPC are not sent.- Slow bet speed, we are sure this is simply a result of the smaller mining power currently on PPC
Anyone wishing to help test PPC gambling may PM us for the URL, smart players may have already guessed how to access the PPC mode
|
|
|
|
smoothie
Legendary
Offline
Activity: 2492
Merit: 1473
LEALANA Bitcoin Grim Reaper
|
|
October 13, 2012, 09:33:40 AM |
|
I wouldn't support anything that even reminds me of RealSolidShit ...AKA Sunny Drag Queen.
|
███████████████████████████████████████
,╓p@@███████@╗╖, ,p████████████████████N, d█████████████████████████b d██████████████████████████████æ ,████²█████████████████████████████, ,█████ ╙████████████████████╨ █████y ██████ `████████████████` ██████ ║██████ Ñ███████████` ███████ ███████ ╩██████Ñ ███████ ███████ ▐▄ ²██╩ a▌ ███████ ╢██████ ▐▓█▄ ▄█▓▌ ███████ ██████ ▐▓▓▓▓▌, ▄█▓▓▓▌ ██████─ ▐▓▓▓▓▓▓█,,▄▓▓▓▓▓▓▌ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓─ ²▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓╩ ▀▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▀ ²▀▀▓▓▓▓▓▓▓▓▓▓▓▓▀▀` ²²² ███████████████████████████████████████
| . ★☆ WWW.LEALANA.COM My PGP fingerprint is A764D833. History of Monero development Visualization ★☆ . LEALANA BITCOIN GRIM REAPER SILVER COINS. |
|
|
|
|