mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Include unit test, Wallet<->SQL updates.
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
//#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "database/SqliteDatabase.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "Config.h"
|
||||
#include "PeerDoor.h"
|
||||
#include "RPCDoor.h"
|
||||
#include "BitcoinUtil.h"
|
||||
#include "key.h"
|
||||
#include "database/SqliteDatabase.h"
|
||||
//#include <boost/log/trivial.hpp>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
Application* theApp=NULL;
|
||||
|
||||
@@ -25,9 +28,7 @@ What needs to happen:
|
||||
Application::Application()
|
||||
{
|
||||
theConfig.load();
|
||||
mKnownNodes.load();
|
||||
//mUNL.load();
|
||||
mWallet.load();
|
||||
mPeerDoor=NULL;
|
||||
mRPCDoor=NULL;
|
||||
mDatabase=NULL;
|
||||
@@ -52,7 +53,7 @@ Application::Application()
|
||||
|
||||
void Application::run()
|
||||
{
|
||||
string filename=strprintf("%sdata.db",theConfig.DATA_DIR.c_str());
|
||||
std::string filename=strprintf("%sdata.db",theConfig.DATA_DIR.c_str());
|
||||
theApp->setDB(new SqliteDatabase(filename.c_str()));
|
||||
mDatabase->connect();
|
||||
|
||||
@@ -70,9 +71,11 @@ void Application::run()
|
||||
|
||||
mConnectionPool.connectToNetwork(mKnownNodes, mIOService);
|
||||
mTimingService.start(mIOService);
|
||||
cout << "Before Run." << endl;
|
||||
std::cout << "Before Run." << std::endl;
|
||||
mIOService.run(); // This blocks
|
||||
|
||||
mWallet.load();
|
||||
|
||||
//BOOST_LOG_TRIVIAL(info) << "Done.";
|
||||
cout << "Done." << endl;
|
||||
std::cout << "Done." << std::endl;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,12 @@ EC_KEY* CKey::GenerateRootDeterministicKey(const uint256& key)
|
||||
if(!ctx) return NULL;
|
||||
|
||||
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if(!pkey)
|
||||
{
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
BIGNUM* order=BN_new();
|
||||
if(!order)
|
||||
@@ -118,6 +124,7 @@ EC_KEY* CKey::GeneratePublicDeterministicKey(const uint160& family, EC_POINT* ro
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
EC_POINT *newPoint=EC_POINT_new(EC_KEY_get0_group(pkey));
|
||||
if(newPoint==NULL)
|
||||
@@ -159,6 +166,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, BIGNUM* roo
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
BIGNUM* order=BN_new();
|
||||
if(order==NULL)
|
||||
|
||||
@@ -71,7 +71,7 @@ CREATE INDEX ObjectLocate ON CommittedObjects(LedgerIndex, ObjType);
|
||||
CREATE TABLE LocalAcctFamilies ( -- a family of accounts that share a payphrase
|
||||
FamilyName CHARACTER(40) PRIMARY KEY,
|
||||
RootPubKey CHARACTER(66),
|
||||
Seq BIGINT UNSIGNED, -- last one issued
|
||||
Seq BIGINT UNSIGNED, -- next one to issue
|
||||
Name TEXT,
|
||||
Comment TEXT
|
||||
)
|
||||
|
||||
187
Wallet.cpp
187
Wallet.cpp
@@ -14,7 +14,7 @@ LocalAccountEntry::LocalAccountEntry(const uint160& accountFamily, int accountSe
|
||||
mBalance(0), mLedgerSeq(0), mTxnSeq(0)
|
||||
{
|
||||
mAcctID=mPublicKey->GetAddress().GetHash160();
|
||||
mPublicKey=theApp->getPubKeyCache().store(mAcctID, mPublicKey);
|
||||
if(theApp!=NULL) mPublicKey=theApp->getPubKeyCache().store(mAcctID, mPublicKey);
|
||||
}
|
||||
|
||||
void LocalAccountEntry::unlock(BIGNUM* rootPrivKey)
|
||||
@@ -34,13 +34,13 @@ std::string LocalAccountEntry::getLocalAccountName() const
|
||||
}
|
||||
|
||||
LocalAccountFamily::LocalAccountFamily(const uint160& family, EC_POINT* pubKey) :
|
||||
mFamily(family), rootPubKey(pubKey), rootPrivateKey(NULL)
|
||||
mFamily(family), mRootPubKey(pubKey), mLastSeq(0), mRootPrivateKey(NULL)
|
||||
{ ; }
|
||||
|
||||
LocalAccountFamily::~LocalAccountFamily()
|
||||
{
|
||||
lock();
|
||||
if(rootPubKey!=NULL) EC_POINT_free(rootPubKey);
|
||||
if(mRootPubKey!=NULL) EC_POINT_free(mRootPubKey);
|
||||
}
|
||||
|
||||
uint160 LocalAccountFamily::getAccount(int seq)
|
||||
@@ -48,7 +48,7 @@ uint160 LocalAccountFamily::getAccount(int seq)
|
||||
std::map<int, LocalAccountEntry::pointer>::iterator ait=mAccounts.find(seq);
|
||||
if(ait!=mAccounts.end()) return ait->second->getAccountID();
|
||||
|
||||
LocalAccountEntry::pointer lae(new LocalAccountEntry(mFamily, seq, rootPubKey));
|
||||
LocalAccountEntry::pointer lae(new LocalAccountEntry(mFamily, seq, mRootPubKey));
|
||||
mAccounts.insert(std::make_pair(seq, lae));
|
||||
|
||||
return lae->getAccountID();
|
||||
@@ -56,27 +56,72 @@ uint160 LocalAccountFamily::getAccount(int seq)
|
||||
|
||||
void LocalAccountFamily::unlock(BIGNUM* privateKey)
|
||||
{
|
||||
if(rootPrivateKey!=NULL) BN_free(rootPrivateKey);
|
||||
rootPrivateKey=privateKey;
|
||||
if(mRootPrivateKey!=NULL) BN_free(mRootPrivateKey);
|
||||
mRootPrivateKey=privateKey;
|
||||
}
|
||||
|
||||
void LocalAccountFamily::lock()
|
||||
{
|
||||
if(rootPrivateKey!=NULL)
|
||||
if(mRootPrivateKey!=NULL)
|
||||
{
|
||||
BN_free(rootPrivateKey);
|
||||
rootPrivateKey=NULL;
|
||||
BN_free(mRootPrivateKey);
|
||||
mRootPrivateKey=NULL;
|
||||
for(std::map<int, LocalAccountEntry::pointer>::iterator it=mAccounts.begin(); it!=mAccounts.end(); ++it)
|
||||
it->second->lock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string LocalAccountFamily::getPubKeyHex() const
|
||||
{
|
||||
EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
if(!grp) return "";
|
||||
|
||||
BIGNUM* pubBase=EC_POINT_point2bn(grp, mRootPubKey, POINT_CONVERSION_COMPRESSED, NULL, NULL);
|
||||
EC_GROUP_free(grp);
|
||||
|
||||
if(!pubBase) return "";
|
||||
char *hex=BN_bn2hex(pubBase);
|
||||
BN_free(pubBase);
|
||||
if(!hex) return "";
|
||||
std::string ret(hex);
|
||||
OPENSSL_free(hex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string LocalAccountFamily::getSQLFields()
|
||||
{
|
||||
return "(FamilyName,RootPubKey,Seq,Name,Comment)";
|
||||
}
|
||||
|
||||
std::string LocalAccountFamily::getSQL() const
|
||||
{ // familyname(40), pubkey(66), seq, name, comment
|
||||
std::string ret("('");
|
||||
ret.append(mFamily.GetHex());
|
||||
ret+="','";
|
||||
ret.append(getPubKeyHex());
|
||||
ret.append("','");
|
||||
ret.append(boost::lexical_cast<std::string>(mLastSeq));
|
||||
ret.append("',");
|
||||
|
||||
std::string esc;
|
||||
theApp->getDB()->escape((const unsigned char *) mName.c_str(), mName.size(), esc);
|
||||
ret.append(esc);
|
||||
ret.append(",");
|
||||
theApp->getDB()->escape((const unsigned char *) mComment.c_str(), mComment.size(), esc);
|
||||
ret.append(esc);
|
||||
|
||||
ret.append(")");
|
||||
return ret;
|
||||
}
|
||||
|
||||
LocalAccountEntry::pointer LocalAccountFamily::get(int seq)
|
||||
{
|
||||
std::map<int, LocalAccountEntry::pointer>::iterator act=mAccounts.find(seq);
|
||||
if(act!=mAccounts.end()) return act->second;
|
||||
|
||||
LocalAccountEntry::pointer ret(new LocalAccountEntry(mFamily, seq, rootPubKey));
|
||||
LocalAccountEntry::pointer ret(new LocalAccountEntry(mFamily, seq, mRootPubKey));
|
||||
mAccounts.insert(std::make_pair(seq, ret));
|
||||
return ret;
|
||||
}
|
||||
@@ -86,54 +131,39 @@ uint160 Wallet::addFamily(const std::string& payPhrase, bool lock)
|
||||
return doPrivate(CKey::PassPhraseToKey(payPhrase), true, !lock);
|
||||
}
|
||||
|
||||
bool Wallet::addFamily(const uint160& familyName, const std::string& pubKey)
|
||||
LocalAccountFamily::pointer Wallet::getFamily(const uint160& family, const std::string& pubKey)
|
||||
{
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=families.find(familyName);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=families.find(family);
|
||||
if(fit!=families.end()) // already added
|
||||
return true;
|
||||
return fit->second;
|
||||
|
||||
EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
if(!grp) return false;
|
||||
if(!grp) return LocalAccountFamily::pointer();
|
||||
|
||||
BIGNUM* pbn=NULL;
|
||||
BN_hex2bn(&pbn, pubKey.c_str());
|
||||
if(!pbn)
|
||||
{
|
||||
EC_GROUP_free(grp);
|
||||
return false;
|
||||
return LocalAccountFamily::pointer();
|
||||
}
|
||||
|
||||
EC_POINT* rootPub=EC_POINT_bn2point(grp, pbn, NULL, NULL);
|
||||
EC_GROUP_free(grp);
|
||||
BN_free(pbn);
|
||||
if(!rootPub)
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
return LocalAccountFamily::pointer();
|
||||
}
|
||||
|
||||
LocalAccountFamily::pointer fam(new LocalAccountFamily(familyName, rootPub));
|
||||
families.insert(std::make_pair(familyName, fam));
|
||||
return true;
|
||||
LocalAccountFamily::pointer fam(new LocalAccountFamily(family, rootPub));
|
||||
families.insert(std::make_pair(family, fam));
|
||||
return fam;
|
||||
}
|
||||
|
||||
std::string Wallet::getPubKey(const uint160& famBase)
|
||||
bool Wallet::addFamily(const uint160& familyName, const std::string& pubKey)
|
||||
{
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=families.find(famBase);
|
||||
if(fit==families.end()) return "";
|
||||
|
||||
EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
if(!grp) return "";
|
||||
|
||||
BIGNUM* pubBase=EC_POINT_point2bn(grp, fit->second->peekPubKey(), POINT_CONVERSION_COMPRESSED, NULL, NULL);
|
||||
EC_GROUP_free(grp);
|
||||
if(!pubBase) return "";
|
||||
char *hex=BN_bn2hex(pubBase);
|
||||
BN_free(pubBase);
|
||||
if(!hex) return "";
|
||||
std::string ret(hex);
|
||||
OPENSSL_free(hex);
|
||||
return ret;
|
||||
return !!getFamily(familyName, pubKey);
|
||||
}
|
||||
|
||||
uint160 LocalAccount::getAddress() const
|
||||
@@ -173,6 +203,40 @@ CKey::pointer LocalAccount::getPrivateKey()
|
||||
|
||||
void Wallet::load()
|
||||
{
|
||||
std::string sql("SELECT * FROM LocalAcctFamilies");
|
||||
|
||||
ScopedLock sl(theApp->getDBLock());
|
||||
Database *db=theApp->getDB();
|
||||
if(!db->executeSQL(sql.c_str())) return;
|
||||
|
||||
while(db->getNextRow())
|
||||
{
|
||||
std::string family, rootpub, name, comment;
|
||||
db->getStr("FamilyName", family);
|
||||
db->getStr("RootPubKey", rootpub);
|
||||
db->getStr("Name", name);
|
||||
db->getStr("Comment", comment);
|
||||
int seq=db->getBigInt("Seq");
|
||||
|
||||
uint160 fb;
|
||||
fb.SetHex(family);
|
||||
|
||||
LocalAccountFamily::pointer f(getFamily(fb, rootpub));
|
||||
if(f)
|
||||
{
|
||||
f->setSeq(seq);
|
||||
f->setName(name);
|
||||
f->setComment(comment);
|
||||
}
|
||||
else assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Wallet::getPubKeyHex(const uint160& famBase)
|
||||
{
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=families.find(famBase);
|
||||
if(fit==families.end()) return "";
|
||||
return fit->second->getPubKeyHex();
|
||||
}
|
||||
|
||||
LocalAccount::pointer Wallet::getLocalAccount(const uint160& family, int seq)
|
||||
@@ -222,3 +286,54 @@ uint160 Wallet::doPrivate(const uint256& passPhrase, bool create, bool unlock)
|
||||
EC_KEY_free(base);
|
||||
return family;
|
||||
}
|
||||
|
||||
bool Wallet::unitTest()
|
||||
{ // Create 100 keys for each of 1,000 families Ensure all keys match
|
||||
Wallet pub, priv;
|
||||
|
||||
uint256 privBase;
|
||||
privBase.SetHex("102031459e");
|
||||
|
||||
for(int i=0; i<1000; i++, privBase++)
|
||||
{
|
||||
uint160 fam=priv.addFamily(privBase, false);
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Priv: " << privBase.GetHex() << " Fam: " << fam.GetHex() << std::endl;
|
||||
#endif
|
||||
|
||||
std::string pubkey=priv.getPubKeyHex(fam);
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Pub: " << pubkey << std::endl;
|
||||
#endif
|
||||
|
||||
if(!pub.addFamily(fam, pubkey))
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int j=0; j<100; j++)
|
||||
{
|
||||
LocalAccount::pointer lpub=pub.getLocalAccount(fam, j);
|
||||
LocalAccount::pointer lpriv=priv.getLocalAccount(fam, j);
|
||||
if(!lpub || !lpriv)
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
uint160 lpuba=lpub->getAddress();
|
||||
uint160 lpriva=lpriv->getAddress();
|
||||
#ifdef DEBUG
|
||||
std::cerr << "pubA(" << j << "): " << lpuba.GetHex() << std::endl;
|
||||
std::cerr << "prvA(" << j << "): " << lpriva.GetHex() << std::endl;
|
||||
#endif
|
||||
if(!lpuba || (lpuba!=lpriva))
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
27
Wallet.h
27
Wallet.h
@@ -67,9 +67,12 @@ protected:
|
||||
std::map<int, LocalAccountEntry::pointer> mAccounts;
|
||||
|
||||
uint160 mFamily; // the name for this account family
|
||||
EC_POINT* rootPubKey;
|
||||
EC_POINT* mRootPubKey;
|
||||
|
||||
BIGNUM* rootPrivateKey;
|
||||
uint32 mLastSeq;
|
||||
std::string mName, mComment;
|
||||
|
||||
BIGNUM* mRootPrivateKey;
|
||||
|
||||
public:
|
||||
|
||||
@@ -77,17 +80,22 @@ public:
|
||||
~LocalAccountFamily();
|
||||
|
||||
const uint160& getFamily() { return mFamily; }
|
||||
bool isLocked() const { return rootPrivateKey==NULL; }
|
||||
bool isLocked() const { return mRootPrivateKey==NULL; }
|
||||
void unlock(BIGNUM* privateKey);
|
||||
void lock();
|
||||
|
||||
const EC_POINT* peekPubKey() const { return rootPubKey; }
|
||||
void setSeq(uint32 s) { mLastSeq=s; }
|
||||
void setName(const std::string& n) { mName=n; }
|
||||
void setComment(const std::string& c) { mComment=c; }
|
||||
|
||||
LocalAccountEntry::pointer get(int seq);
|
||||
uint160 getAccount(int seq);
|
||||
|
||||
std::string getPubName() const; // The text name of the public key
|
||||
std::string getPubKeyHex() const; // The text name of the public key
|
||||
std::string getShortName() const; // The text name for the family
|
||||
|
||||
static std::string getSQLFields();
|
||||
std::string getSQL() const;
|
||||
};
|
||||
|
||||
class LocalAccount
|
||||
@@ -125,6 +133,11 @@ protected:
|
||||
|
||||
uint160 doPrivate(const uint256& passPhrase, bool create, bool unlock);
|
||||
|
||||
LocalAccountFamily::pointer getFamily(const uint160& family, const std::string& pubKey);
|
||||
|
||||
void addFamily(const uint160& family, const std::string& pubKey, int seq,
|
||||
const std::string& name, const std::string& comment);
|
||||
|
||||
public:
|
||||
Wallet() { ; }
|
||||
|
||||
@@ -140,7 +153,9 @@ public:
|
||||
|
||||
LocalAccount::pointer getLocalAccount(const uint160& famBase, int seq);
|
||||
LocalAccount::pointer getLocalAccount(const uint160& acctID);
|
||||
std::string getPubKey(const uint160& famBase);
|
||||
std::string getPubKeyHex(const uint160& famBase);
|
||||
|
||||
static bool unitTest();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user