mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-30 07:55:51 +00:00
Infrastructure for local transactions, wallet interface.
Transaction JSON code.
This commit is contained in:
@@ -285,7 +285,7 @@ bool Ledger::unitTest()
|
|||||||
as=ledger->getAccountState(la2);
|
as=ledger->getAccountState(la2);
|
||||||
assert(!as);
|
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());
|
assert(!!t->getID());
|
||||||
|
|
||||||
Ledger::TransResult tr=ledger->applyTransaction(t);
|
Ledger::TransResult tr=ledger->applyTransaction(t);
|
||||||
|
|||||||
17
LocalTransaction.cpp
Normal file
17
LocalTransaction.cpp
Normal 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;
|
||||||
|
}
|
||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
const std::string& getComment() const { return mComment; }
|
const std::string& getComment() const { return mComment; }
|
||||||
Transaction::pointer getTransaction() { return mTransaction; }
|
Transaction::pointer getTransaction() { return mTransaction; }
|
||||||
|
|
||||||
bool makeTransaction(void);
|
bool makeTransaction();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -71,10 +71,10 @@ SRCS= keystore.cpp BitcoinUtil.cpp \
|
|||||||
Application.cpp TimingService.cpp KnownNodeList.cpp ConnectionPool.cpp Peer.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 \
|
PeerDoor.cpp RPCDoor.cpp RPCServer.cpp rpc.cpp Conversion.cpp RequestParser.cpp HashedObject.cpp \
|
||||||
UniqueNodeList.cpp PubKeyCache.cpp SHAMapDiff.cpp DeterministicKeys.cpp LedgerMaster.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
|
DBSRCS= SqliteDatabase.cpp database.cpp
|
||||||
DBSRCC=sqlite3.c
|
DBSRCC= sqlite3.c
|
||||||
|
|
||||||
UTILSRCS= pugixml.cpp
|
UTILSRCS= pugixml.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "RPC.h"
|
#include "RPC.h"
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
#include "Conversion.h"
|
#include "Conversion.h"
|
||||||
|
#include "LocalTransaction.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Just read from wire until the entire request is in.
|
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);
|
w.write(std::cerr, valParams);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Json::Value result=doCommand(strMethod, valParams);
|
Json::Value result(doCommand(strMethod, valParams));
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
w.write(std::cerr, result);
|
w.write(std::cerr, result);
|
||||||
@@ -317,8 +318,57 @@ Json::Value RPCServer::doSendTo(Json::Value& params)
|
|||||||
// sendto <destination> <amount> <tag>
|
// sendto <destination> <amount> <tag>
|
||||||
if(!params.isArray() || (params.size()<2))
|
if(!params.isArray() || (params.size()<2))
|
||||||
return JSONRPCError(500, "Invalid parameters");
|
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)
|
Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params)
|
||||||
|
|||||||
@@ -14,16 +14,17 @@ Transaction::Transaction() : mTransactionID(0), mAccountFrom(0), mAccountTo(0),
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::Transaction(TransStatus status, LocalAccount::pointer fromLocalAccount, uint32 fromSeq,
|
Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const uint160& toAccount, uint64 amount,
|
||||||
const uint160& toAccount, uint64 amount, uint32 ident, uint32 ledger) :
|
uint32 ident, uint32 ledger) :
|
||||||
mAccountTo(toAccount), mAmount(amount), mFromAccountSeq(fromSeq), mSourceLedger(ledger),
|
mAccountTo(toAccount), mAmount(amount), mSourceLedger(ledger), mIdent(ident), mInLedger(0), mStatus(NEW)
|
||||||
mIdent(ident), mInLedger(0), mStatus(NEW)
|
|
||||||
{
|
{
|
||||||
mAccountFrom=fromLocalAccount->getAddress();
|
mAccountFrom=fromLocalAccount->getAddress();
|
||||||
mFromPubKey=fromLocalAccount->getPublicKey();
|
mFromPubKey=fromLocalAccount->getPublicKey();
|
||||||
|
mFromAccountSeq=fromLocalAccount->getAcctSeq();
|
||||||
|
if(!mFromAccountSeq) mStatus=INCOMPLETE;
|
||||||
assert(mFromPubKey);
|
assert(mFromPubKey);
|
||||||
updateFee();
|
updateFee();
|
||||||
sign(fromLocalAccount);
|
if(!sign(fromLocalAccount)) mStatus=INCOMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::Transaction(const std::vector<unsigned char> &t, bool validate) : mStatus(INVALID)
|
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;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
#ifndef __TRANSACTION__
|
#ifndef __TRANSACTION__
|
||||||
#define __TRANSACTION__
|
#define __TRANSACTION__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
|
|
||||||
|
#include "json/value.h"
|
||||||
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "newcoin.pb.h"
|
#include "newcoin.pb.h"
|
||||||
@@ -52,8 +56,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
Transaction();
|
Transaction();
|
||||||
Transaction(const std::vector<unsigned char>& rawTransaction, bool validate);
|
Transaction(const std::vector<unsigned char>& rawTransaction, bool validate);
|
||||||
Transaction(TransStatus Status, LocalAccount::pointer fromLocal, uint32 fromSeq, const uint160& to, uint64 amount,
|
Transaction(LocalAccount::pointer fromLocal, const uint160& to, uint64 amount, uint32 ident, uint32 ledger);
|
||||||
uint32 ident, uint32 ledger);
|
|
||||||
|
|
||||||
bool sign(LocalAccount::pointer fromLocalAccount);
|
bool sign(LocalAccount::pointer fromLocalAccount);
|
||||||
bool checkSign() const;
|
bool checkSign() const;
|
||||||
@@ -96,6 +99,8 @@ public:
|
|||||||
bool operator<=(const Transaction&) const;
|
bool operator<=(const Transaction&) const;
|
||||||
bool operator>=(const Transaction&) const;
|
bool operator>=(const Transaction&) const;
|
||||||
|
|
||||||
|
Json::Value getJson(bool decorate) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static Transaction::pointer transactionFromSQL(const std::string& statement);
|
static Transaction::pointer transactionFromSQL(const std::string& statement);
|
||||||
Transaction(const uint256& transactionID, const uint160& accountFrom, const uint160& accountTo,
|
Transaction(const uint256& transactionID, const uint160& accountFrom, const uint160& accountTo,
|
||||||
|
|||||||
15
Wallet.cpp
15
Wallet.cpp
@@ -4,6 +4,7 @@
|
|||||||
#include "openssl/rand.h"
|
#include "openssl/rand.h"
|
||||||
#include "openssl/ec.h"
|
#include "openssl/ec.h"
|
||||||
|
|
||||||
|
#include "boost/foreach.hpp"
|
||||||
#include "boost/lexical_cast.hpp"
|
#include "boost/lexical_cast.hpp"
|
||||||
|
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
@@ -361,6 +362,11 @@ std::string LocalAccount::getFullName() const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LocalAccount::isLocked() const
|
||||||
|
{
|
||||||
|
return mFamily->isLocked();
|
||||||
|
}
|
||||||
|
|
||||||
std::string LocalAccount::getFamilyName() const
|
std::string LocalAccount::getFamilyName() const
|
||||||
{
|
{
|
||||||
return mFamily->getShortName();
|
return mFamily->getShortName();
|
||||||
@@ -549,6 +555,15 @@ LocalAccount::pointer Wallet::getLocalAccount(const uint160& acctID)
|
|||||||
return ait->second;
|
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)
|
LocalAccount::pointer Wallet::parseAccount(const std::string& specifier)
|
||||||
{ // <family>:<seq> or <acct_id>
|
{ // <family>:<seq> or <acct_id>
|
||||||
|
|
||||||
|
|||||||
1
Wallet.h
1
Wallet.h
@@ -181,6 +181,7 @@ public:
|
|||||||
LocalAccount::pointer getLocalAccount(const uint160& famBase, int seq);
|
LocalAccount::pointer getLocalAccount(const uint160& famBase, int seq);
|
||||||
LocalAccount::pointer getLocalAccount(const uint160& acctID);
|
LocalAccount::pointer getLocalAccount(const uint160& acctID);
|
||||||
LocalAccount::pointer getNewLocalAccount(const uint160& family);
|
LocalAccount::pointer getNewLocalAccount(const uint160& family);
|
||||||
|
LocalAccount::pointer findAccountForTransaction(uint64 amount);
|
||||||
uint160 peekKey(const uint160& family, int seq);
|
uint160 peekKey(const uint160& family, int seq);
|
||||||
std::string getPubGenHex(const uint160& famBase);
|
std::string getPubGenHex(const uint160& famBase);
|
||||||
std::string getShortName(const uint160& famBase);
|
std::string getShortName(const uint160& famBase);
|
||||||
|
|||||||
Reference in New Issue
Block a user