Infrastructure for local transactions, wallet interface.

Transaction JSON code.
This commit is contained in:
JoelKatz
2012-01-08 22:18:03 -08:00
parent f87d1bfcb7
commit fa16bb430b
9 changed files with 145 additions and 13 deletions

View File

@@ -285,7 +285,7 @@ bool Ledger::unitTest()
as=ledger->getAccountState(la2);
assert(!as);
Transaction::pointer t(new Transaction(NEW, l1, l1->getAcctSeq(), l2->getAddress(), 2500, 0, 1));
Transaction::pointer t(new Transaction(l1, l2->getAddress(), 2500, 0, 1));
assert(!!t->getID());
Ledger::TransResult tr=ledger->applyTransaction(t);

17
LocalTransaction.cpp Normal file
View File

@@ -0,0 +1,17 @@
#include "LocalTransaction.h"
#include "Application.h"
#include "Wallet.h"
bool LocalTransaction::makeTransaction()
{
if(!!mTransaction) return true;
LocalAccount::pointer lac(theApp->getWallet().findAccountForTransaction(mAmount));
if(!lac) return false;
mTransaction=Transaction::pointer(new Transaction(lac, mDestAcctID, mAmount, mTag,
theApp->getOPs().getCurrentLedgerID()));
if(mTransaction->getStatus()!=NEW) return false;
return true;
}

View File

@@ -37,7 +37,7 @@ public:
const std::string& getComment() const { return mComment; }
Transaction::pointer getTransaction() { return mTransaction; }
bool makeTransaction(void);
bool makeTransaction();
};
#endif

View File

@@ -71,10 +71,10 @@ SRCS= keystore.cpp BitcoinUtil.cpp \
Application.cpp TimingService.cpp KnownNodeList.cpp ConnectionPool.cpp Peer.cpp \
PeerDoor.cpp RPCDoor.cpp RPCServer.cpp rpc.cpp Conversion.cpp RequestParser.cpp HashedObject.cpp \
UniqueNodeList.cpp PubKeyCache.cpp SHAMapDiff.cpp DeterministicKeys.cpp LedgerMaster.cpp \
LedgerHistory.cpp NetworkOPs.cpp CallRPC.cpp DBInit.cpp
LedgerHistory.cpp NetworkOPs.cpp CallRPC.cpp DBInit.cpp LocalTransaction.cpp
DBSRCS= SqliteDatabase.cpp database.cpp
DBSRCC=sqlite3.c
DBSRCC= sqlite3.c
UTILSRCS= pugixml.cpp

View File

@@ -16,6 +16,7 @@
#include "RPC.h"
#include "Wallet.h"
#include "Conversion.h"
#include "LocalTransaction.h"
/*
Just read from wire until the entire request is in.
@@ -103,7 +104,7 @@ std::string RPCServer::handleRequest(const std::string& requestStr)
w.write(std::cerr, valParams);
#endif
Json::Value result=doCommand(strMethod, valParams);
Json::Value result(doCommand(strMethod, valParams));
#ifdef DEBUG
w.write(std::cerr, result);
@@ -317,8 +318,57 @@ Json::Value RPCServer::doSendTo(Json::Value& params)
// sendto <destination> <amount> <tag>
if(!params.isArray() || (params.size()<2))
return JSONRPCError(500, "Invalid parameters");
int paramCount=getParamCount(params);
if((paramCount<2)||(paramCount>3))
return JSONRPCError(500, "Invalid parameters");
return "Not yet";
std::string sDest, sAmount;
if(!extractString(sDest, params, 0) || !extractString(sAmount, params, 1))
return JSONRPCError(500, "Invalid parameters");
uint160 destAccount=parseAccount(sDest);
if(!destAccount)
return JSONRPCError(500, "Unable to parse destination account");
uint64 iAmount;
try
{
iAmount=boost::lexical_cast<uint64>(sAmount);
if(iAmount<=0) return JSONRPCError(500, "Invalid amount");
}
catch (...)
{
return JSONRPCError(500, "Invalid amount");
}
uint32 iTag(0);
try
{
if(paramCount>2)
{
std::string sTag;
extractString(sTag, params, 2);
iTag=boost::lexical_cast<uint32>(sTag);
}
}
catch (...)
{
return JSONRPCError(500, "Invalid tag");
}
#ifdef DEBUG
std::cerr << "SendTo(" << destAccount.GetHex() << ") amount=" << iAmount <<
", tag=" << iTag << std::endl;
#endif
LocalTransaction::pointer lt(new LocalTransaction(destAccount, iAmount, iTag));
if(!lt->makeTransaction())
return JSONRPCError(500, "Insufficient funds in unlocked accounts");
// WRITEME - process transaction
return lt->getTransaction()->getJson(true);
}
Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params)

View File

@@ -14,16 +14,17 @@ Transaction::Transaction() : mTransactionID(0), mAccountFrom(0), mAccountTo(0),
{
}
Transaction::Transaction(TransStatus status, LocalAccount::pointer fromLocalAccount, uint32 fromSeq,
const uint160& toAccount, uint64 amount, uint32 ident, uint32 ledger) :
mAccountTo(toAccount), mAmount(amount), mFromAccountSeq(fromSeq), mSourceLedger(ledger),
mIdent(ident), mInLedger(0), mStatus(NEW)
Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const uint160& toAccount, uint64 amount,
uint32 ident, uint32 ledger) :
mAccountTo(toAccount), mAmount(amount), mSourceLedger(ledger), mIdent(ident), mInLedger(0), mStatus(NEW)
{
mAccountFrom=fromLocalAccount->getAddress();
mFromPubKey=fromLocalAccount->getPublicKey();
mFromAccountSeq=fromLocalAccount->getAcctSeq();
if(!mFromAccountSeq) mStatus=INCOMPLETE;
assert(mFromPubKey);
updateFee();
sign(fromLocalAccount);
if(!sign(fromLocalAccount)) mStatus=INCOMPLETE;
}
Transaction::Transaction(const std::vector<unsigned char> &t, bool validate) : mStatus(INVALID)
@@ -279,3 +280,46 @@ bool Transaction::convertToTransactions(uint32 firstLedgerSeq, uint32 secondLedg
}
return ret;
}
Json::Value Transaction::getJson(bool decorate) const
{
Json::Value ret(Json::objectValue);
ret["TransactionID"]=mTransactionID.GetHex();
ret["Amount"]=boost::lexical_cast<std::string>(mAmount);
ret["Fee"]=boost::lexical_cast<std::string>(mFee);
if(mInLedger) ret["InLedger"]=mInLedger;
switch(mStatus)
{
case NEW: ret["Status"]="new"; break;
case INVALID: ret["Status"]="invalid"; break;
case INCLUDED: ret["Status"]="included"; break;
case CONFLICTED: ret["Status"]="conflicted"; break;
case COMMITTED: ret["Status"]="committed"; break;
case HELD: ret["Status"]="held"; break;
case REMOVED: ret["Status"]="removed"; break;
case OBSOLETE: ret["Status"]="obsolete"; break;
case INCOMPLETE: ret["Status"]="incomplete"; break;
default: ret["Status"]="unknown";
}
Json::Value source(Json::objectValue);
source["AccountID"]=NewcoinAddress(mAccountFrom).GetString();
source["AccountSeq"]=mFromAccountSeq;
source["Ledger"]=mSourceLedger;
if(!!mIdent) source["Identifier"]=mIdent;
Json::Value destination(Json::objectValue);
destination["AccountID"]=NewcoinAddress(mAccountTo).GetString();
if(decorate)
{
LocalAccount::pointer lac=theApp->getWallet().getLocalAccount(mAccountFrom);
if(!!lac) source=lac->getJson();
lac=theApp->getWallet().getLocalAccount(mAccountTo);
if(!!lac) destination=lac->getJson();
}
ret["Source"]=source;
ret["Destination"]=destination;
return ret;
}

View File

@@ -1,10 +1,14 @@
#ifndef __TRANSACTION__
#define __TRANSACTION__
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/cstdint.hpp>
#include "json/value.h"
#include "key.h"
#include "uint256.h"
#include "newcoin.pb.h"
@@ -52,8 +56,7 @@ private:
public:
Transaction();
Transaction(const std::vector<unsigned char>& rawTransaction, bool validate);
Transaction(TransStatus Status, LocalAccount::pointer fromLocal, uint32 fromSeq, const uint160& to, uint64 amount,
uint32 ident, uint32 ledger);
Transaction(LocalAccount::pointer fromLocal, const uint160& to, uint64 amount, uint32 ident, uint32 ledger);
bool sign(LocalAccount::pointer fromLocalAccount);
bool checkSign() const;
@@ -96,6 +99,8 @@ public:
bool operator<=(const Transaction&) const;
bool operator>=(const Transaction&) const;
Json::Value getJson(bool decorate) const;
protected:
static Transaction::pointer transactionFromSQL(const std::string& statement);
Transaction(const uint256& transactionID, const uint160& accountFrom, const uint160& accountTo,

View File

@@ -4,6 +4,7 @@
#include "openssl/rand.h"
#include "openssl/ec.h"
#include "boost/foreach.hpp"
#include "boost/lexical_cast.hpp"
#include "Wallet.h"
@@ -361,6 +362,11 @@ std::string LocalAccount::getFullName() const
return ret;
}
bool LocalAccount::isLocked() const
{
return mFamily->isLocked();
}
std::string LocalAccount::getFamilyName() const
{
return mFamily->getShortName();
@@ -549,6 +555,15 @@ LocalAccount::pointer Wallet::getLocalAccount(const uint160& acctID)
return ait->second;
}
LocalAccount::pointer Wallet::findAccountForTransaction(uint64 amount)
{
boost::recursive_mutex::scoped_lock sl(mLock);
for(std::map<uint160, LocalAccount::pointer>::iterator it=mAccounts.begin(); it!=mAccounts.end(); ++it)
if(!it->second->isLocked() && (it->second->getBalance()>=amount) )
return it->second;
return LocalAccount::pointer();
}
LocalAccount::pointer Wallet::parseAccount(const std::string& specifier)
{ // <family>:<seq> or <acct_id>

View File

@@ -181,6 +181,7 @@ public:
LocalAccount::pointer getLocalAccount(const uint160& famBase, int seq);
LocalAccount::pointer getLocalAccount(const uint160& acctID);
LocalAccount::pointer getNewLocalAccount(const uint160& family);
LocalAccount::pointer findAccountForTransaction(uint64 amount);
uint160 peekKey(const uint160& family, int seq);
std::string getPubGenHex(const uint160& famBase);
std::string getShortName(const uint160& famBase);