Rework addresses.

This commit is contained in:
Arthur Britto
2012-03-17 20:19:09 -07:00
parent 6e8421dd99
commit 73ff9b95ad
33 changed files with 1287 additions and 708 deletions

View File

@@ -43,7 +43,7 @@ env.Append(LIBS = [
DEBUGFLAGS = ['-g', '-DDEBUG']
env.Append(LINKFLAGS = ['-rdynamic', '-pthread'])
env.Append(CCFLAGS = ['-pthread', '-Wall', '-Wno-sign-compare', '-Wno-char-subscripts'])
env.Append(CCFLAGS = ['-pthread', '-Wall', '-Wno-sign-compare', '-Wno-char-subscripts', '-DSQLITE_THREADSAFE'])
env.Append(CXXFLAGS = ['-O0', '-pthread', '-Wno-invalid-offsetof', '-Wformat']+DEBUGFLAGS)
DB_SRCS = glob.glob('database/*.c') + glob.glob('database/*.cpp')

View File

@@ -8,19 +8,21 @@ AccountState::AccountState(const std::vector<unsigned char>& v)
{
Serializer s(v);
mValid=false;
if(!s.get160(mAccountID, 0)) { assert(false); return; }
uint160 acct160 = mAccountID.getAccountID();
if(!s.get160(acct160, 0)) { assert(false); return; }
if(!s.get64(mBalance, 20)) { assert(false); return; }
if(!s.get32(mAccountSeq, 28)) { assert(false); return; }
mValid=true;
}
AccountState::AccountState(const uint160& id) : mAccountID(id), mBalance(0), mAccountSeq(0), mValid(true)
AccountState::AccountState(const NewcoinAddress& id) : mAccountID(id), mBalance(0), mAccountSeq(0), mValid(true)
{ ; }
std::vector<unsigned char> AccountState::getRaw() const
{ // 20-byte acct ID, 8-byte balance, 4-byte sequence
Serializer s(32);
s.add160(mAccountID);
s.add160(mAccountID.getAccountID());
s.add64(mBalance);
s.add32(mAccountSeq);
return s.getData();
@@ -45,10 +47,13 @@ bool AccountState::isHexAccountID(const std::string& acct)
void AccountState::addJson(Json::Value& val)
{
Json::Value as(Json::objectValue);
as["Account"]=mAccountID.GetHex();
// XXX Might want account public here, if available.
as["Account"]=mAccountID.humanAccountID();
as["Balance"]=boost::lexical_cast<std::string>(mBalance);
as["SendSequence"]=mAccountSeq;
if(!mValid) as["Invalid"]=true;
NewcoinAddress nad(mAccountID);
val[nad.GetString()]=as;
val[mAccountID.humanAccountID()]=as;
}
// vim:ts=4

View File

@@ -11,6 +11,7 @@
#include "types.h"
#include "uint256.h"
#include "NewcoinAddress.h"
class AccountState
{
@@ -18,16 +19,16 @@ public:
typedef boost::shared_ptr<AccountState> pointer;
private:
uint160 mAccountID;
NewcoinAddress mAccountID;
uint64 mBalance;
uint32 mAccountSeq;
bool mValid;
public:
AccountState(const uint160& mAccountID); // new account
AccountState(const NewcoinAddress& mAccountID); // new account
AccountState(const std::vector<unsigned char>&); // raw form
const uint160& getAccountID() const { return mAccountID; }
const NewcoinAddress& getAccountID() const { return mAccountID; }
uint64 getBalance() const { return mBalance; }
uint32 getSeq() const { return mAccountSeq; }
@@ -57,3 +58,4 @@ public:
};
#endif
// vim:ts=4

View File

@@ -76,7 +76,14 @@ void Application::run()
std::cout << "Before Run." << std::endl;
// Temporary root account will be ["This is my payphrase."]:0
uint160 rootAddress=NewcoinAddress("MoXdEKxkG1FEwyuMia6Mbrja1SohefRvro").GetHash160();
NewcoinAddress rootFamilySeed;
rootFamilySeed.setFamilySeed(CKey::PassPhraseToKey("This is my payphrase"));
NewcoinAddress rootFamilyGenerator;
rootFamilyGenerator.setFamilyGenerator(rootFamilySeed);
NewcoinAddress rootAddress;
rootAddress.setAccountPublic(rootFamilyGenerator, 0);
Ledger::pointer firstLedger(new Ledger(rootAddress, 100000000));
firstLedger->setClosed();

View File

@@ -49,10 +49,8 @@ int LedgerDBCount=sizeof(LedgerDBInit)/sizeof(const char *);
// Wallet database holds local accounts and trusted nodes
const char *WalletDBInit[] = {
"CREATE TABLE LocalAcctFamilies ( \
FamilyName CHARACTER(40) PRIMARY KEY, \
RootPubKey CHARACTER(66), \
FamilyGenerator CHARACTER(53) PRIMARY KEY, \
Seq BIGINT UNSIGNED, \
Name TEXT, \
Comment TEXT \
);",
"CREATE TABLE LocalAccounts ( \
@@ -62,15 +60,16 @@ const char *WalletDBInit[] = {
Seq BIGINT UNSIGNED, \
Balance BIGINT UNSIGNED, \
LedgerSeq BIGINT UNSIGNED, \
Name TEXT, \
Comment TEXT \
);",
"CREATE TABLE TrustedNodes ( ` \
"CREATE TABLE TrustedNodes ( \
Hanko CHARACTER(40) PRIMARY KEY, \
TrustLevel SMALLINT, \
PubKey CHARACTER(66), \
Comment TEXT \
);" };
// TrustLevel SMALLINT,
int WalletDBCount=sizeof(WalletDBInit)/sizeof(const char *);
@@ -98,3 +97,5 @@ const char *NetNodeDBInit[] = {
int NetNodeDBCount=sizeof(NetNodeDBInit)/sizeof(const char *);
// vim:ts=4

View File

@@ -7,16 +7,23 @@
#include "Serializer.h"
uint256 CKey::PassPhraseToKey(const std::string& passPhrase)
// <-- seed
uint128 CKey::PassPhraseToKey(const std::string& passPhrase)
{
Serializer s;
s.addRaw(passPhrase.c_str(), passPhrase.size());
uint256 ret(s.getSHA512Half());
uint256 hash256 = s.getSHA512Half();
uint128 ret(hash256);
s.secureErase();
return ret;
}
EC_KEY* CKey::GenerateRootDeterministicKey(const uint256& key)
// --> seed
// <-- private root generator + public root generator
EC_KEY* CKey::GenerateRootDeterministicKey(const uint128& seed)
{
BN_CTX* ctx=BN_CTX_new();
if(!ctx) return NULL;
@@ -49,8 +56,8 @@ EC_KEY* CKey::GenerateRootDeterministicKey(const uint256& key)
int seq=0;
do
{ // private key must be non-zero and less than the curve's order
Serializer s(72);
s.add256(key);
Serializer s((128+32)/8);
s.add128(seed);
s.add32(seq++);
uint256 root=s.getSHA512Half();
s.secureErase();
@@ -102,22 +109,23 @@ EC_KEY* CKey::GenerateRootDeterministicKey(const uint256& key)
return pkey;
}
EC_KEY* CKey::GenerateRootPubKey(const std::string& pubHex)
// Take newcoin address.
// --> root public generator (consumes)
// <-- root public generator in EC format
EC_KEY* CKey::GenerateRootPubKey(BIGNUM* pubGenerator)
{
BIGNUM* bn=NULL;
BN_hex2bn(&bn, pubHex.c_str());
if(bn==NULL) return NULL;
if(pubGenerator==NULL) return NULL;
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
if(!pkey)
{
BN_free(bn);
BN_free(pubGenerator);
return NULL;
}
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
EC_POINT* pubPoint=EC_POINT_bn2point(EC_KEY_get0_group(pkey), bn, NULL, NULL);
BN_free(bn);
EC_POINT* pubPoint=EC_POINT_bn2point(EC_KEY_get0_group(pkey), pubGenerator, NULL, NULL);
BN_free(pubGenerator);
if(!pubPoint)
{
EC_KEY_free(pkey);
@@ -134,14 +142,15 @@ EC_KEY* CKey::GenerateRootPubKey(const std::string& pubHex)
return pkey;
}
static BIGNUM* makeHash(const uint160& family, int seq, BIGNUM* order)
// --> public generator
static BIGNUM* makeHash(const NewcoinAddress& family, int seq, BIGNUM* order)
{
int subSeq=0;
BIGNUM* ret=NULL;
do
{
Serializer s(28);
s.add160(family);
Serializer s((128+32+32)/8);
s.add128(family.getFamilySeed());
s.add32(seq);
s.add32(subSeq++);
uint256 root=s.getSHA512Half();
@@ -149,64 +158,66 @@ static BIGNUM* makeHash(const uint160& family, int seq, BIGNUM* order)
ret=BN_bin2bn((const unsigned char *) &root, sizeof(root), ret);
if(!ret) return NULL;
} while (BN_is_zero(ret) || (BN_cmp(ret, order)>=0));
return ret;
}
EC_KEY* CKey::GeneratePublicDeterministicKey(const uint160& family, const EC_POINT* rootPubKey, int seq)
// --> public generator
EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& family, int seq)
{ // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
EC_KEY* rootKey = CKey::GenerateRootPubKey(family.getFamilyGeneratorBN());
const EC_POINT* rootPubKey = EC_KEY_get0_public_key(rootKey);
BN_CTX* ctx = BN_CTX_new();
if(ctx==NULL) return NULL;
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
if(pkey==NULL)
{
BN_CTX_free(ctx);
return NULL;
}
EC_POINT* newPoint = 0;
BIGNUM* order = 0;
BIGNUM* hash = 0;
bool success = true;
if (!ctx || !pkey) success = false;
if (success)
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
EC_POINT *newPoint=EC_POINT_new(EC_KEY_get0_group(pkey));
if(newPoint==NULL)
{
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
if (success) {
newPoint = EC_POINT_new(EC_KEY_get0_group(pkey));
if(!newPoint) success = false;
}
BIGNUM* order=BN_new();
if (success) {
order = BN_new();
if(!order || !EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
{
if(order) BN_free(order);
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
success = false;
}
// calculate the private additional key
BIGNUM* hash=makeHash(family, seq, order);
BN_free(order);
if(hash==NULL)
{
EC_POINT_free(newPoint);
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
// Calculate the private additional key.
if (success) {
hash = makeHash(family, seq, order);
if(!hash) success = false;
}
// calculate the corresponding public key
if (success) {
// Calculate the corresponding public key.
EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx);
BN_free(hash);
// add the master public key and set
// Add the master public key and set.
EC_POINT_add(EC_KEY_get0_group(pkey), newPoint, newPoint, rootPubKey, ctx);
EC_KEY_set_public_key(pkey, newPoint);
EC_POINT_free(newPoint);
BN_CTX_free(ctx);
return pkey;
}
EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, const BIGNUM* rootPrivKey, int seq)
if (order) BN_free(order);
if (hash) BN_free(hash);
if (newPoint) EC_POINT_free(newPoint);
if (ctx) BN_CTX_free(ctx);
if (rootKey) EC_KEY_free(rootKey);
if (pkey && !success) EC_KEY_free(pkey);
return success ? pkey : NULL;
}
// --> root private key
EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& family, const BIGNUM* rootPrivKey, int seq)
{ // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
BN_CTX* ctx=BN_CTX_new();
if(ctx==NULL) return NULL;
@@ -271,5 +282,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, const BIGNU
EC_POINT_free(pubKey);
BN_CTX_free(ctx);
return pkey;
}
// vim:ts=4

View File

@@ -15,7 +15,7 @@
#include "Wallet.h"
#include "BinaryFormats.h"
Ledger::Ledger(const uint160& masterID, uint64 startAmount) :
Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) :
mFeeHeld(0), mTimeStamp(0), mLedgerSeq(0),
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false)
{
@@ -110,13 +110,13 @@ void Ledger::addRaw(Serializer &s)
s.add64(mTimeStamp);
}
AccountState::pointer Ledger::getAccountState(const uint160& accountID)
AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID)
{
#ifdef DEBUG
std::cerr << "Ledger:getAccountState(" << accountID.GetHex() << ")" << std::endl;
std::cerr << "Ledger:getAccountState(" << accountID.humanAccountID() << ")" << std::endl;
#endif
ScopedLock l(mTransactionMap->Lock());
SHAMapItem::pointer item=mAccountStateMap->peekItem(accountID.to256());
SHAMapItem::pointer item=mAccountStateMap->peekItem(accountID.getAccountID().to256());
if(!item)
{
#ifdef DEBUG
@@ -127,10 +127,10 @@ AccountState::pointer Ledger::getAccountState(const uint160& accountID)
return boost::make_shared<AccountState>(item->getData());
}
uint64 Ledger::getBalance(const uint160& accountID) const
uint64 Ledger::getBalance(const NewcoinAddress& accountID) const
{
ScopedLock l(mTransactionMap->Lock());
SHAMapItem::pointer item=mAccountStateMap->peekItem(accountID.to256());
SHAMapItem::pointer item=mAccountStateMap->peekItem(accountID.getAccountID().to256());
if(!item) return 0;
return AccountState(item->getData()).getBalance();
}
@@ -138,7 +138,7 @@ uint64 Ledger::getBalance(const uint160& accountID) const
bool Ledger::updateAccountState(AccountState::pointer state)
{
assert(!mAccepted);
SHAMapItem::pointer item=boost::make_shared<SHAMapItem>(state->getAccountID(), state->getRaw());
SHAMapItem::pointer item=boost::make_shared<SHAMapItem>(state->getAccountID().getAccountID(), state->getRaw());
return mAccountStateMap->updateGiveItem(item, false);
}
@@ -146,7 +146,7 @@ bool Ledger::addAccountState(AccountState::pointer state)
{
assert(!mAccepted);
assert( (state->getBalance()==0) || (state->getSeq()>0) );
SHAMapItem::pointer item=boost::make_shared<SHAMapItem>(state->getAccountID(), state->getRaw());
SHAMapItem::pointer item=boost::make_shared<SHAMapItem>(state->getAccountID().getAccountID(), state->getRaw());
return mAccountStateMap->addGiveItem(item, false);
}
@@ -345,6 +345,7 @@ void LocalAccount::syncLedger()
bool Ledger::unitTest()
{
#if 0
uint160 la1=theApp->getWallet().addFamily(CKey::PassPhraseToKey("This is my payphrase!"), false);
uint160 la2=theApp->getWallet().addFamily(CKey::PassPhraseToKey("Another payphrase"), false);
@@ -354,8 +355,8 @@ bool Ledger::unitTest()
assert(l1->getAddress()==la1);
#ifdef DEBUG
std::cerr << "Account1: " << la1.GetHex() << std::endl;
std::cerr << "Account2: " << la2.GetHex() << std::endl;
std::cerr << "Account1: " << la1.humanAccountID() << std::endl;
std::cerr << "Account2: " << la2.humanAccountID() << std::endl;
#endif
Ledger::pointer ledger=boost::make_shared<Ledger>(la1, 100000);
@@ -377,7 +378,7 @@ bool Ledger::unitTest()
std::cerr << "Transaction: " << tr << std::endl;
#endif
assert(tr==TR_SUCCESS);
#endif
return true;
}

View File

@@ -63,7 +63,7 @@ protected:
static Ledger::pointer getSQL(const std::string& sqlStatement);
public:
Ledger(const uint160& masterID, uint64 startAmount); // used for the starting bootstrap ledger
Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
uint64 feeHeld, uint64 timeStamp, uint32 ledgerSeq); // used for received ledgers
Ledger(const std::vector<unsigned char>& rawLedger);
@@ -97,9 +97,9 @@ public:
// mid level functions
bool hasTransaction(const uint256& TransID) const;
AccountState::pointer getAccountState(const uint160& acctID);
AccountState::pointer getAccountState(const NewcoinAddress& acctID);
Transaction::pointer getTransaction(const uint256& transID) const;
uint64 getBalance(const uint160& acctID) const;
uint64 getBalance(const NewcoinAddress& acctID) const;
// high level functions
TransResult applyTransaction(Transaction::pointer trans);

View File

@@ -14,14 +14,18 @@ uint32 LedgerMaster::getCurrentLedgerIndex()
return mCurrentLedger->getLedgerSeq();
}
uint64 LedgerMaster::getBalance(const uint160& addr)
uint64 LedgerMaster::getBalance(const NewcoinAddress& acctID)
{
return mCurrentLedger->getBalance(addr);
return mCurrentLedger->getBalance(acctID);
}
uint64 LedgerMaster::getBalance(std::string& addr)
uint64 LedgerMaster::getBalance(std::string& strAcctID)
{
return mCurrentLedger->getBalance(humanTo160(addr));
NewcoinAddress acctID;
acctID.setAccountID(strAcctID);
return mCurrentLedger->getBalance(acctID);
}
bool LedgerMaster::addHeldTransaction(Transaction::pointer transaction)
@@ -194,3 +198,4 @@ theApp->getConnectionPool().relayMessage(NULL,msg);
*/
#endif
// vim:ts=4

View File

@@ -54,9 +54,9 @@ public:
return mLedgerHistory.getLedgerByHash(hash);
}
uint64 getBalance(std::string& addr);
uint64 getBalance(const uint160& addr);
AccountState::pointer getAccountState(const uint160& addr)
uint64 getBalance(std::string& strAcctID);
uint64 getBalance(const NewcoinAddress& acctID);
AccountState::pointer getAccountState(const NewcoinAddress& addr)
{ return mCurrentLedger->getAccountState(addr); }
bool addHeldTransaction(Transaction::pointer trans);

View File

@@ -14,8 +14,8 @@ public:
protected:
// core account information
CKey::pointer mPublicKey;
uint160 mAcctID;
std::string mName, mComment;
NewcoinAddress mAcctID;
std::string mComment;
// family information
boost::shared_ptr<LocalAccountFamily> mFamily;
@@ -35,13 +35,10 @@ public:
bool updateName(); // writes changed name/comment
bool updateBalance(); // writes changed balance/seq
const uint160& getAddress() const { return mAcctID; }
const NewcoinAddress& getAddress() const { return mAcctID; }
int getAcctFSeq() const { return mAccountFSeq; }
std::string getLocalAccountName() const; // The name used locally to identify this account
std::string getAccountName() const; // The normal account name used to send to this account
std::string getFullName() const;
std::string getShortName() const;
std::string getFamilyName() const;
bool isLocked() const;
@@ -71,44 +68,40 @@ public:
protected:
std::map<int, LocalAccount::pointer> mAccounts;
uint160 mFamily; // the name for this account family
EC_POINT* mRootPubKey;
NewcoinAddress mFamily; // Family generator
uint32 mLastSeq;
std::string mName, mComment;
std::string mComment;
BIGNUM* mRootPrivateKey;
public:
LocalAccountFamily(const uint160& family, const EC_GROUP* group, const EC_POINT* pubKey);
LocalAccountFamily(const NewcoinAddress& family);
~LocalAccountFamily();
const uint160& getFamily() const { return mFamily; }
const NewcoinAddress& getFamily() const { return mFamily; }
void unlock(const BIGNUM* privateKey);
void unlock(BIGNUM* privateKey);
void lock();
bool isLocked() const { return mRootPrivateKey==NULL; }
void setSeq(uint32 s) { mLastSeq=s; }
uint32 getSeq() { return mLastSeq; }
void setName(const std::string& n) { mName=n; }
void setComment(const std::string& c) { mComment=c; }
std::map<int, LocalAccount::pointer>& getAcctMap() { return mAccounts; }
LocalAccount::pointer get(int seq);
uint160 getAccount(int seq, bool keep);
NewcoinAddress getAccount(int seq, bool keep);
CKey::pointer getPrivateKey(int seq);
CKey::pointer getPublicKey(int seq);
std::string getPubGenHex() const; // The text name of the public key
std::string getShortName() const { return mName; }
std::string getComment() const { return mComment; }
Json::Value getJson() const;
static std::string getSQLFields();
std::string getSQL() const;
static LocalAccountFamily::pointer readFamily(const uint160& family);
static LocalAccountFamily::pointer readFamily(const NewcoinAddress& family);
void write(bool is_new);
};

View File

@@ -27,7 +27,6 @@ bool LocalTransaction::makeTransaction()
Json::Value t=mTransaction->getJson(true);
Json::StyledStreamWriter w;
w.write(std::cerr, t);
#endif
return false;
}
@@ -46,11 +45,16 @@ Json::Value LocalTransaction::getJson() const
Json::Value ret(Json::objectValue);
ret["Status"]="unfunded";
ret["Amount"]=boost::lexical_cast<std::string>(mAmount);
Json::Value destination(Json::objectValue);
destination["AccountID"]=NewcoinAddress(mDestAcctID).GetString();
destination["AccountID"]=mDestAcctID.humanAccountID();
ret["Destination"]=destination;
return ret;
}
return mTransaction->getJson(true, isPaid(), isCredited());
}
// vim:ts=4

View File

@@ -20,7 +20,7 @@ public:
protected:
// core specifications
uint160 mDestAcctID;
NewcoinAddress mDestAcctID;
uint64 mAmount;
uint32 mTag;
std::string mComment;
@@ -30,11 +30,11 @@ protected:
public:
LocalTransaction(const uint160 &dest, uint64 amount, uint32 tag) :
LocalTransaction(const NewcoinAddress &dest, uint64 amount, uint32 tag) :
mDestAcctID(dest), mAmount(amount), mTag(tag), mPaid(false), mCredited(false) { ; }
void setComment(const std::string& comment) { mComment=comment; }
const uint160& getDestinationAccount() const { return mDestAcctID; }
const NewcoinAddress& getDestinationAccount() const { return mDestAcctID; }
uint64 getAmount() const { return mAmount; }
uint32 getTag() const { return mTag; }
const std::string& getComment() const { return mComment; }

View File

@@ -97,7 +97,7 @@ Transaction::pointer NetworkOPs::findTransactionByID(const uint256& transactionI
}
int NetworkOPs::findTransactionsBySource(std::list<Transaction::pointer>& txns,
const uint160& sourceAccount, uint32 minSeq, uint32 maxSeq)
const NewcoinAddress& sourceAccount, uint32 minSeq, uint32 maxSeq)
{
AccountState::pointer state=getAccountState(sourceAccount);
if(!state) return 0;
@@ -119,13 +119,13 @@ int NetworkOPs::findTransactionsBySource(std::list<Transaction::pointer>& txns,
}
int NetworkOPs::findTransactionsByDestination(std::list<Transaction::pointer>& txns,
const uint160& destinationAccount, uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions)
const NewcoinAddress& destinationAccount, uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions)
{
// WRITEME
return 0;
}
AccountState::pointer NetworkOPs::getAccountState(const uint160& accountID)
AccountState::pointer NetworkOPs::getAccountState(const NewcoinAddress& accountID)
{
return theApp->getMasterLedger().getCurrentLedger()->getAccountState(accountID);
}

View File

@@ -36,13 +36,13 @@ public:
// transaction operations
Transaction::pointer processTransaction(Transaction::pointer transaction, Peer* source=NULL);
Transaction::pointer findTransactionByID(const uint256& transactionID);
int findTransactionsBySource(std::list<Transaction::pointer>&, const uint160& sourceAccount,
int findTransactionsBySource(std::list<Transaction::pointer>&, const NewcoinAddress& sourceAccount,
uint32 minSeq, uint32 maxSeq);
int findTransactionsByDestination(std::list<Transaction::pointer>&, const uint160& destinationAccount,
int findTransactionsByDestination(std::list<Transaction::pointer>&, const NewcoinAddress& destinationAccount,
uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions);
// account operations
AccountState::pointer getAccountState(const uint160& accountID);
AccountState::pointer getAccountState(const NewcoinAddress& accountID);
// contact block operations

View File

@@ -1,58 +1,514 @@
#include "NewcoinAddress.h"
#include "key.h"
#include "Config.h"
#include "BitcoinUtil.h"
#include "openssl/ec.h"
#include <cassert>
bool NewcoinAddress::SetHash160(const uint160& hash160)
NewcoinAddress::NewcoinAddress()
{
SetData(51, &hash160, 20);
return true;
}
bool NewcoinAddress::SetPubKey(const std::vector<unsigned char>& vchPubKey)
{
return SetHash160(Hash160(vchPubKey));
version = VER_NONE;
}
bool NewcoinAddress::IsValid()
{
return nVersion == 51 && vchData.size() == 20;
return !vchData.empty();
}
NewcoinAddress::NewcoinAddress()
//
// Hanko
//
uint160 NewcoinAddress::getHanko() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_HANKO:
return uint160(vchData);
case VER_NODE_PUBLIC:
// Note, we are encoding the left or right.
return Hash160(vchData);
default:
std::runtime_error("bad source");
}
NewcoinAddress::NewcoinAddress(const uint160& hash160In)
{
SetHash160(hash160In);
return 0;
}
NewcoinAddress::NewcoinAddress(const std::vector<unsigned char>& vchPubKey)
std::string NewcoinAddress::humanHanko() const
{
SetPubKey(vchPubKey);
}
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
NewcoinAddress::NewcoinAddress(const std::string& strAddress)
{
SetString(strAddress);
}
NewcoinAddress::NewcoinAddress(const char* pszAddress)
{
SetString(pszAddress);
}
uint160 NewcoinAddress::GetHash160() const
{
assert(vchData.size() == 20);
uint160 hash160;
memcpy(&hash160, &vchData[0], 20);
return hash160;
}
std::string NewcoinAddress::GetString() const
{
case VER_HANKO:
return ToString();
case VER_NODE_PUBLIC:
{
NewcoinAddress hanko;
(void) hanko.setHanko(getHanko());
return hanko.ToString();
}
default:
std::runtime_error("bad source");
}
return 0;
}
bool NewcoinAddress::setHanko(const std::string& strHanko)
{
return SetString(strHanko.c_str(), VER_HANKO);
}
void NewcoinAddress::setHanko(const uint160& hash160)
{
SetData(VER_HANKO, hash160.begin(), 20);
}
//
// NodePublic
//
const std::vector<unsigned char>& NewcoinAddress::getNodePublic() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_HANKO:
std::runtime_error("public not available from hanko");
break;
case VER_NODE_PUBLIC:
// Do nothing.
break;
default:
std::runtime_error("bad source");
}
return vchData;
}
std::string NewcoinAddress::humanNodePublic() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_HANKO:
std::runtime_error("public not available from hanko");
break;
case VER_NODE_PUBLIC:
return ToString();
default:
std::runtime_error("bad source");
}
return 0;
}
bool NewcoinAddress::setNodePublic(const std::string& strPublic)
{
return SetString(strPublic.c_str(), VER_NODE_PUBLIC);
}
void NewcoinAddress::setNodePublic(const std::vector<unsigned char>& vPublic)
{
SetData(VER_NODE_PUBLIC, vPublic);
}
//
// NodePrivate
//
uint256 NewcoinAddress::getNodePrivate() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_NODE_PRIVATE:
// Nothing
break;
default:
std::runtime_error("bad source");
}
return uint256(vchData);
}
std::string NewcoinAddress::humanNodePrivate() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_NODE_PRIVATE:
return ToString();
default:
std::runtime_error("bad source");
}
return 0;
}
bool NewcoinAddress::setNodePrivate(const std::string& strPrivate)
{
return SetString(strPrivate.c_str(), VER_NODE_PRIVATE);
}
void NewcoinAddress::setNodePrivate(uint256 hash256)
{
SetData(VER_NODE_PRIVATE, hash256.begin(), 32);
}
//
// AccountID
//
uint160 NewcoinAddress::getAccountID() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_ACCOUNT_ID:
return uint160(vchData);
case VER_ACCOUNT_PUBLIC:
// Note, we are encoding the left or right.
return Hash160(vchData);
default:
std::runtime_error("bad source");
}
return 0;
}
std::string NewcoinAddress::humanAccountID() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_ACCOUNT_ID:
return ToString();
case VER_ACCOUNT_PUBLIC:
{
NewcoinAddress accountID;
(void) accountID.setHanko(getAccountID());
return accountID.ToString();
}
default:
std::runtime_error("bad source");
}
return 0;
}
bool NewcoinAddress::setAccountID(const std::string& strAccountID)
{
return SetString(strAccountID.c_str(), VER_ACCOUNT_ID);
}
void NewcoinAddress::setAccountID(const uint160& hash160)
{
SetData(VER_ACCOUNT_ID, hash160.begin(), 20);
}
//
// AccountPublic
//
const std::vector<unsigned char>& NewcoinAddress::getAccountPublic() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_ACCOUNT_ID:
std::runtime_error("public not available from account id");
break;
case VER_ACCOUNT_PUBLIC:
// Do nothing.
break;
default:
std::runtime_error("bad source");
}
return vchData;
}
std::string NewcoinAddress::humanAccountPublic() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_ACCOUNT_ID:
std::runtime_error("public not available from account id");
break;
case VER_ACCOUNT_PUBLIC:
return ToString();
default:
std::runtime_error("bad source");
}
return 0;
}
bool NewcoinAddress::setAccountPublic(const std::string& strPublic)
{
return SetString(strPublic.c_str(), VER_ACCOUNT_PUBLIC);
}
void NewcoinAddress::setAccountPublic(const std::vector<unsigned char>& vPublic)
{
SetData(VER_ACCOUNT_PUBLIC, vPublic);
}
void NewcoinAddress::setAccountPublic(const NewcoinAddress& generator, int seq)
{
CKey pubkey = CKey(generator, seq);
setAccountPublic(pubkey.GetPubKey());
}
//
// AccountPrivate
//
uint256 NewcoinAddress::getAccountPrivate() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_ACCOUNT_PRIVATE:
// Do nothing.
break;
default:
std::runtime_error("bad source");
}
return uint256(vchData);
}
std::string NewcoinAddress::humanAccountPrivate() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_ACCOUNT_PRIVATE:
return ToString();
default:
std::runtime_error("bad source");
}
return 0;
}
bool NewcoinAddress::setAccountPrivate(const std::string& strPrivate)
{
return SetString(strPrivate.c_str(), VER_ACCOUNT_PRIVATE);
}
void NewcoinAddress::setAccountPrivate(uint256 hash256)
{
SetData(VER_ACCOUNT_PRIVATE, hash256.begin(), 32);
}
//
// Family Generators
//
BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_FAMILY_GENERATOR:
// Do nothing.
break;
default:
std::runtime_error("bad source");
}
// Convert to big-endian
unsigned char be[vchData.size()];
std::reverse_copy(vchData.begin(), vchData.end(), &be[0]);
return BN_bin2bn(be, vchData.size(), NULL);
}
const std::vector<unsigned char>& NewcoinAddress::getFamilyGenerator() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_FAMILY_GENERATOR:
// Do nothing.
break;
default:
std::runtime_error("bad source");
}
return vchData;
}
std::string NewcoinAddress::humanFamilyGenerator() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_FAMILY_GENERATOR:
return ToString();
default:
std::runtime_error("bad source");
}
return 0;
}
// YYY Would be nice if you could pass a family seed and derive the generator.
bool NewcoinAddress::setFamilyGenerator(const std::string& strGenerator)
{
return SetString(strGenerator.c_str(), VER_FAMILY_GENERATOR);
}
void NewcoinAddress::setFamilyGenerator(const std::vector<unsigned char>& vPublic)
{
SetData(VER_FAMILY_GENERATOR, vPublic);
}
void NewcoinAddress::setFamilyGenerator(const NewcoinAddress& seed)
{
seed.seedInfo(this, 0);
}
//
// Family Seed
//
void NewcoinAddress::seedInfo(NewcoinAddress* dstGenerator, BIGNUM** dstPrivateKey) const
{
// Generate root key
EC_KEY *base=CKey::GenerateRootDeterministicKey(getFamilySeed());
// Extract family name
std::vector<unsigned char> rootPubKey(33, 0);
unsigned char *begin=&rootPubKey[0];
i2o_ECPublicKey(base, &begin);
while(rootPubKey.size()<33) rootPubKey.push_back((unsigned char)0);
if (dstGenerator)
dstGenerator->setFamilyGenerator(rootPubKey);
if (dstPrivateKey)
*dstPrivateKey = BN_dup(EC_KEY_get0_private_key(base));
EC_KEY_free(base);
}
uint128 NewcoinAddress::getFamilySeed() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_FAMILY_SEED:
// Do nothing.
break;
default:
std::runtime_error("bad source");
}
return uint128(vchData);
}
BIGNUM* NewcoinAddress::getFamilyPrivateKey() const
{
BIGNUM* ret;
seedInfo(0, &ret);
return ret;
}
std::string NewcoinAddress::humanFamilySeed() const
{
switch (version) {
case VER_NONE:
std::runtime_error("unset source");
break;
case VER_FAMILY_SEED:
return ToString();
default:
std::runtime_error("bad source");
}
return 0;
}
bool NewcoinAddress::setFamilySeed(const std::string& strSeed)
{
return SetString(strSeed.c_str(), VER_FAMILY_SEED);
}
void NewcoinAddress::setFamilySeed(uint128 hash128) {
SetData(VER_FAMILY_SEED, hash128.begin(), 16);
}
// vim:ts=4

View File

@@ -2,26 +2,96 @@
#define __NEWCOIN_ADDRESS__
#include "base58.h"
#include "uint256.h"
// TODO: https://en.bitcoin.it/wiki/Address
// TODO: Why do we need steps 5 and 6? why not just use a checksum function to get the checksum?
//
// Used to hold addresses and parse and produce human formats.
//
class NewcoinAddress : public CBase58Data
{
private:
typedef enum {
VER_NONE = 1,
VER_HANKO = 13,
VER_NODE_PUBLIC = 18,
VER_NODE_PRIVATE = 23,
VER_ACCOUNT_ID = 0,
VER_ACCOUNT_PUBLIC = 3,
VER_ACCOUNT_PRIVATE = 8,
VER_FAMILY_GENERATOR = 28,
VER_FAMILY_SEED = 33,
} VersionEncoding;
VersionEncoding version;
void seedInfo(NewcoinAddress* dstGenerator, BIGNUM** dstPrivateKey) const;
public:
NewcoinAddress();
NewcoinAddress(const uint160& hash160In);
NewcoinAddress(const std::vector<unsigned char>& vchPubKey);
NewcoinAddress(const std::string& strAddress);
NewcoinAddress(const char* pszAddress);
bool SetHash160(const uint160& hash160);
bool SetPubKey(const std::vector<unsigned char>& vchPubKey);
bool IsValid();
uint160 GetHash160() const;
std::string GetString() const;
//
// Nodes
//
uint160 getHanko() const;
const std::vector<unsigned char>& getNodePublic() const;
uint256 getNodePrivate() const;
std::string humanHanko() const;
std::string humanNodePublic() const;
std::string humanNodePrivate() const;
bool setHanko(const std::string& strHanko);
void setHanko(const uint160& hash160);
bool setNodePublic(const std::string& strPublic);
void setNodePublic(const std::vector<unsigned char>& vPublic);
bool setNodePrivate(const std::string& strPrivate);
void setNodePrivate(uint256 hash256);
//
// Accounts
//
uint160 getAccountID() const;
const std::vector<unsigned char>& getAccountPublic() const;
uint256 getAccountPrivate() const;
std::string humanAccountID() const;
std::string humanAccountPublic() const;
std::string humanAccountPrivate() const;
bool setAccountID(const std::string& strAccountID);
void setAccountID(const uint160& hash160In);
bool setAccountPublic(const std::string& strPublic);
void setAccountPublic(const std::vector<unsigned char>& vPublic);
void setAccountPublic(const NewcoinAddress& generator, int seq);
bool setAccountPrivate(const std::string& strPrivate);
void setAccountPrivate(uint256 hash256);
//
// Family Generators
//
BIGNUM* getFamilyGeneratorBN() const;
const std::vector<unsigned char>& getFamilyGenerator() const;
std::string humanFamilyGenerator() const;
bool setFamilyGenerator(const std::string& strGenerator);
void setFamilyGenerator(const std::vector<unsigned char>& vPublic);
void setFamilyGenerator(const NewcoinAddress& seed);
//
// Family Seeds
//
uint128 getFamilySeed() const;
BIGNUM* getFamilyPrivateKey() const;
std::string humanFamilySeed() const;
bool setFamilySeed(const std::string& strSeed);
void setFamilySeed(uint128 hash128);
};
#endif

View File

@@ -4,17 +4,17 @@
#include "boost/interprocess/sync/scoped_lock.hpp"
CKey::pointer PubKeyCache::locate(const uint160& id)
CKey::pointer PubKeyCache::locate(const NewcoinAddress& id)
{
if(1)
{ // is it in cache
boost::mutex::scoped_lock sl(mLock);
std::map<uint160, CKey::pointer>::iterator it(mCache.find(id));
std::map<NewcoinAddress, CKey::pointer>::iterator it(mCache.find(id));
if(it!=mCache.end()) return it->second;
}
std::string sql="SELECT * from PubKeys WHERE ID='";
sql.append(id.GetHex());
sql.append(id.humanAccountID());
sql.append("';'");
std::vector<unsigned char> data;
data.reserve(65); // our public keys are actually 33 bytes
@@ -44,17 +44,17 @@ CKey::pointer PubKeyCache::locate(const uint160& id)
return ckp;
}
CKey::pointer PubKeyCache::store(const uint160& id, CKey::pointer key)
CKey::pointer PubKeyCache::store(const NewcoinAddress& id, CKey::pointer key)
{ // stored if needed, returns cached copy (possibly the original)
if(1)
{
boost::mutex::scoped_lock sl(mLock);
std::pair<std::map<uint160,CKey::pointer>::iterator, bool> pit(mCache.insert(std::make_pair(id, key)));
std::pair<std::map<NewcoinAddress,CKey::pointer>::iterator, bool> pit(mCache.insert(std::make_pair(id, key)));
if(!pit.second) // there was an existing key
return pit.first->second;
}
std::string sql="INSERT INTO PubKeys (ID,PubKey) VALUES ('";
sql+=id.GetHex();
sql+=id.humanAccountID();
sql+="',";
std::vector<unsigned char> pk=key->GetPubKey();

View File

@@ -5,20 +5,20 @@
#include <boost/thread/mutex.hpp>
#include "uint256.h"
#include "NewcoinAddress.h"
#include "key.h"
class PubKeyCache
{
private:
boost::mutex mLock;
std::map<uint160, CKey::pointer> mCache;
std::map<NewcoinAddress, CKey::pointer> mCache;
public:
PubKeyCache() { ; }
CKey::pointer locate(const uint160& id);
CKey::pointer store(const uint160& id, CKey::pointer key);
CKey::pointer locate(const NewcoinAddress& id);
CKey::pointer store(const NewcoinAddress& id, CKey::pointer key);
void clear();
};

View File

@@ -154,47 +154,60 @@ bool RPCServer::extractString(std::string& param, const Json::Value& params, int
return true;
}
uint160 RPCServer::parseFamily(const std::string& fParam)
NewcoinAddress RPCServer::parseFamily(const std::string& fParam)
{
uint160 family;
if(Wallet::isHexFamily(fParam))
family.SetHex(fParam);
else if(Wallet::isHexPublicKey(fParam))
family=theApp->getWallet().findFamilyPK(fParam);
else
family=theApp->getWallet().findFamilySN(fParam);
NewcoinAddress family;
if(family.setFamilyGenerator(fParam))
{
family = theApp->getWallet().findFamilyPK(family);
}
return family;
}
Json::Value RPCServer::doCreateFamily(Json::Value& params)
{
// createfamily <hexPrivateKey>
// createfamily <hexPublicKey>
// createfamily FXXXX
// createfamily fXXXX
// createfamily "<pass phrase>"
// createfamily
std::string query;
uint160 family;
NewcoinAddress family;
NewcoinAddress seed;
uint256 privKey;
if(!extractString(query, params, 0))
family=theApp->getWallet().addRandomFamily(privKey);
else if(Wallet::isHexPrivateKey(query))
family=theApp->getWallet().addFamily(Wallet::textToPrivKey(query), false);
else if(Wallet::isHexPublicKey(query))
family=theApp->getWallet().addFamily(query);
{
// No parameters, generate a family from a random seed.
family=theApp->getWallet().addRandomFamily(seed);
}
else if(seed.setFamilySeed(query))
{
// Had a family seed.
family=theApp->getWallet().addFamily(seed, false);
}
else if(family.setFamilyGenerator(query))
{
// Had a public generator
family=theApp->getWallet().addFamily(family);
}
else
{
// Must be a pass phrase.
family=theApp->getWallet().addFamily(query, false);
if(!family)
}
if(!family.IsValid())
return JSONRPCError(500, "Invalid family specifier");
Json::Value ret(theApp->getWallet().getFamilyJson(family));
if(ret.isNull()) return JSONRPCError(500, "Invalid family");
if(!!privKey)
if(seed.IsValid())
{
ret["PrivateGenerator"]=Wallet::privKeyToText(privKey);
privKey.zero();
ret["FamilySeed"]=seed.humanFamilySeed();
}
return ret;
}
@@ -208,14 +221,9 @@ Json::Value RPCServer::doAccountInfo(Json::Value &params)
LocalAccount::pointer account=theApp->getWallet().parseAccount(acct);
if(account) return account->getJson();
uint160 acctid;
if(AccountState::isHexAccountID(acct)) acctid.SetHex(acct);
else
{
NewcoinAddress ad(acct);
if(ad.IsValid()) acctid=ad.GetHash160();
}
if(!acctid) return JSONRPCError(500, "Unable to parse account");
NewcoinAddress acctid;
if (!acctid.setAccountID(acct))
return JSONRPCError(500, "Unable to parse account");
LocalAccount::pointer lac(theApp->getWallet().getLocalAccount(acctid));
if(!!lac) return lac->getJson();
@@ -226,8 +234,9 @@ Json::Value RPCServer::doAccountInfo(Json::Value &params)
as->addJson(ret);
else
{
NewcoinAddress ad(acctid);
ret[ad.GetString()]="NotFound";
NewcoinAddress ad;
ad.setAccountID(acct);
ret[ad.humanAccountID()]="NotFound";
}
return ret;
}
@@ -238,12 +247,13 @@ Json::Value RPCServer::doNewAccount(Json::Value &params)
if(!extractString(fParam, params, 0))
return JSONRPCError(500, "Family required");
uint160 family = parseFamily(fParam);
if(!family) return JSONRPCError(500, "No such family");
NewcoinAddress family = parseFamily(fParam);
if(!family.IsValid()) return JSONRPCError(500, "Family not found.");
LocalAccount::pointer account(theApp->getWallet().getNewLocalAccount(family));
if(!account)
return JSONRPCError(500, "Family not found");
return account->getJson();
}
@@ -251,38 +261,48 @@ Json::Value RPCServer::doLock(Json::Value &params)
{ // lock <family>
// lock
std::string fParam;
if(extractString(fParam, params, 0))
{ // local <family>
uint160 family = parseFamily(fParam);
if(!family) return JSONRPCError(500, "Family not found");
NewcoinAddress family = parseFamily(fParam);
if(!family.IsValid()) return JSONRPCError(500, "Family not found");
theApp->getWallet().lock(family);
return "locked";
}
else
{
theApp->getWallet().lock();
return "locked";
}
return "locked";
}
Json::Value RPCServer::doUnlock(Json::Value &params)
{ // unlock <hexPrivateKey>
{ // unlock FXXXX
// unlock "<pass phrase>"
std::string param;
if(!extractString(param, params, 0) || Wallet::isHexPublicKey(param))
NewcoinAddress familyGenerator;
if(!extractString(param, params, 0) || familyGenerator.setFamilyGenerator(param))
return JSONRPCError(500, "Private key required");
uint160 family;
if(Wallet::isHexPrivateKey(param))
family=theApp->getWallet().addFamily(Wallet::textToPrivKey(param), false);
NewcoinAddress family;
NewcoinAddress familySeed;
if(familySeed.setFamilySeed(param))
// FXXX
family=theApp->getWallet().addFamily(familySeed, false);
else
// pass phrase
family=theApp->getWallet().addFamily(param, false);
if(!family)
if(!family.IsValid())
return JSONRPCError(500, "Bad family");
Json::Value ret(theApp->getWallet().getFamilyJson(family));
if(ret.isNull()) return JSONRPCError(500, "Invalid family");
return ret;
}
@@ -295,11 +315,11 @@ Json::Value RPCServer::doFamilyInfo(Json::Value &params)
if(paramCount==0)
{
std::vector<uint160> familyIDs;
std::vector<NewcoinAddress> familyIDs;
theApp->getWallet().getFamilies(familyIDs);
Json::Value ret(Json::arrayValue);
BOOST_FOREACH(const uint160& fid, familyIDs)
BOOST_FOREACH(const NewcoinAddress& fid, familyIDs)
{
Json::Value obj(theApp->getWallet().getFamilyJson(fid));
if(!obj.isNull()) ret.append(obj);
@@ -311,8 +331,9 @@ Json::Value RPCServer::doFamilyInfo(Json::Value &params)
std::string fParam;
extractString(fParam, params, 0);
uint160 family=parseFamily(fParam);
if(!family) return JSONRPCError(500, "No such family");
NewcoinAddress family=parseFamily(fParam);
if(!family.IsValid()) return JSONRPCError(500, "No such family");
Json::Value obj(theApp->getWallet().getFamilyJson(family));
if(obj.isNull())
return JSONRPCError(500, "Family not found");
@@ -322,12 +343,13 @@ Json::Value RPCServer::doFamilyInfo(Json::Value &params)
std::string keyNum;
extractString(keyNum, params, 1);
int kn=boost::lexical_cast<int>(keyNum);
uint160 k=theApp->getWallet().peekKey(family, kn);
if(!!k)
NewcoinAddress k=theApp->getWallet().peekKey(family, kn);
if(k.IsValid())
{
Json::Value key(Json::objectValue);
key["Number"]=kn;
key["Address"]=NewcoinAddress(k).GetString();
key["Address"]=k.humanAccountID();
obj["Account"]=key;
}
}
@@ -370,8 +392,8 @@ Json::Value RPCServer::doSendTo(Json::Value& params)
if(!extractString(sDest, params, 0) || !extractString(sAmount, params, 1))
return JSONRPCError(500, "Invalid parameters");
uint160 destAccount=parseAccount(sDest);
if(!destAccount)
NewcoinAddress destAccount = parseAccount(sDest);
if(!destAccount.IsValid())
return JSONRPCError(500, "Unable to parse destination account");
uint64 iAmount;
@@ -401,7 +423,7 @@ Json::Value RPCServer::doSendTo(Json::Value& params)
}
#ifdef DEBUG
std::cerr << "SendTo(" << destAccount.GetHex() << ") amount=" << iAmount <<
std::cerr << "SendTo(" << destAccount.humanAccountID() << ") amount=" << iAmount <<
", tag=" << iTag << std::endl;
#endif
@@ -476,6 +498,39 @@ Json::Value RPCServer::doLedger(Json::Value& params)
return "not implemented";
}
Json::Value RPCServer::doAddUnl(Json::Value& params) {
// addUNL <node_public>
// addUNL <node_public> <comment>
if(params.size()==1 || params.size()==2)
{
std::string pubKey=params[0u].asString();
std::string comment=params.size() == 2
? ""
: params[1u].asString();
NewcoinAddress nodePublic;
if(nodePublic.setNodePublic(pubKey))
{
theApp->getUNL().addNode(nodePublic, comment);
return "adding node";
}
else
{
return "invalid public key";
}
}
else return "invalid params";
}
Json::Value RPCServer::doGetUnl(Json::Value& params) {
std::string str;
theApp->getUNL().dumpUNL(str);
return str.c_str();
}
Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params)
{
std::cerr << "RPC:" << command << std::endl;
@@ -484,24 +539,8 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
mSocket.get_io_service().stop();
return "newcoin server stopping";
}
if(command== "addUNL")
{
if(params.size()==2)
{
uint160 hanko=humanTo160(params[0u].asString());
std::vector<unsigned char> pubKey;
humanToPK(params[1u].asString(),pubKey);
theApp->getUNL().addNode(hanko,pubKey);
return "adding node";
}
else return "invalid params";
}
if(command=="getUNL")
{
std::string str;
theApp->getUNL().dumpUNL(str);
return(str.c_str());
}
if(command=="addUNL") return doAddUnl(params);
if(command=="getUNL") return doGetUnl(params);
if(command=="createfamily") return doCreateFamily(params);
if(command=="familyinfo") return doFamilyInfo(params);
if(command=="accountinfo") return doAccountInfo(params);
@@ -526,19 +565,23 @@ void RPCServer::sendReply()
void RPCServer::handle_write(const boost::system::error_code& /*error*/)
{
}
uint160 RPCServer::parseAccount(const std::string& account)
NewcoinAddress RPCServer::parseAccount(const std::string& account)
{ // FIXME: Support local wallet key names
if(account.find(':')!=std::string::npos)
{ // local account in family:seq form
LocalAccount::pointer lac(theApp->getWallet().parseAccount(account));
if(!lac) return uint160();
return lac->getAddress();
return lac
? lac->getAddress()
: NewcoinAddress();
}
NewcoinAddress nac(account);
if(!nac.IsValid()) return uint160();
return nac.GetHash160();
NewcoinAddress *nap = new NewcoinAddress();
nap->setAccountID(account) || nap->setAccountPublic(account);
return *nap;
}
// vim:ts=4

View File

@@ -7,7 +7,7 @@
#include "HttpRequest.h"
#include "RequestParser.h"
#include "uint256.h"
#include "NewcoinAddress.h"
class RPCServer : public boost::enable_shared_from_this<RPCServer>
{
@@ -31,7 +31,7 @@ class RPCServer : public boost::enable_shared_from_this<RPCServer>
int getParamCount(const Json::Value& params);
bool extractString(std::string& param, const Json::Value& params, int index);
uint160 parseFamily(const std::string& family);
NewcoinAddress parseFamily(const std::string& family);
Json::Value doCreateFamily(Json::Value& params);
Json::Value doFamilyInfo(Json::Value& params);
@@ -45,10 +45,11 @@ class RPCServer : public boost::enable_shared_from_this<RPCServer>
Json::Value doTx(Json::Value& params);
Json::Value doLedger(Json::Value& params);
Json::Value doAccount(Json::Value& params);
Json::Value doAddUnl(Json::Value& params);
Json::Value doGetUnl(Json::Value& params);
// parses a string account name into a uint160
// can be local or remote
uint160 parseAccount(const std::string& account);
// Parses a string account name into a local or remote NewcoinAddress.
NewcoinAddress parseAccount(const std::string& account);
public:
typedef boost::shared_ptr<RPCServer> pointer;

View File

@@ -36,6 +36,13 @@ int Serializer::add64(uint64 i)
return ret;
}
int Serializer::add128(const uint128& i)
{
int ret=mData.size();
mData.insert(mData.end(), i.begin(), i.end());
return ret;
}
int Serializer::add160(const uint160& i)
{
int ret=mData.size();

View File

@@ -30,6 +30,7 @@ class Serializer
int add16(uint16);
int add32(uint32); // ledger indexes, account sequence
int add64(uint64); // timestamps, amounts
int add128(const uint128&); // private key generators
int add160(const uint160&); // account names, hankos
int add256(const uint256&); // transaction and ledger hashes
int addRaw(const std::vector<unsigned char> &vector);
@@ -120,3 +121,4 @@ public:
};
#endif
// vim:ts=4

View File

@@ -11,13 +11,13 @@
using namespace std;
Transaction::Transaction() : mTransactionID(0), mAccountFrom(0), mAccountTo(0),
Transaction::Transaction() : mTransactionID(0), mAccountFrom(), mAccountTo(),
mAmount(0), mFee(0), mFromAccountSeq(0), mSourceLedger(0), mIdent(0),
mInLedger(0), mStatus(INVALID)
{
}
Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const uint160& toAccount, uint64 amount,
Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAddress& toAccount, uint64 amount,
uint32 ident, uint32 ledger) :
mAccountTo(toAccount), mAmount(amount), mSourceLedger(ledger), mIdent(ident), mInLedger(0), mStatus(NEW)
{
@@ -52,9 +52,12 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const uint160&
Transaction::Transaction(const std::vector<unsigned char> &t, bool validate) : mStatus(INVALID)
{
uint160 toAccountID;
uint160 fromAccountID;
Serializer s(t);
if(s.getLength()<BTxSize) { assert(false); return; }
if(!s.get160(mAccountTo, BTxPDestAcct)) { assert(false); return; }
if(!s.get160(toAccountID, BTxPDestAcct)) { assert(false); return; }
if(!s.get64(mAmount, BTxPAmount)) { assert(false); return; }
if(!s.get32(mFromAccountSeq, BTxPSASeq)) { assert(false); return; }
if(!s.get32(mSourceLedger, BTxPSLIdx)) { assert(false); return; }
@@ -63,9 +66,13 @@ Transaction::Transaction(const std::vector<unsigned char> &t, bool validate) : m
std::vector<unsigned char> pubKey;
if(!s.getRaw(pubKey, BTxPSPubK, BTxLSPubK)) { assert(false); return; }
mAccountTo.setAccountID(toAccountID);
mAccountFrom.setAccountID(fromAccountID);
mFromPubKey=boost::make_shared<CKey>();
if(!mFromPubKey->SetPubKey(pubKey)) return;
mAccountFrom=Hash160(pubKey);
mAccountFrom.setAccountPublic(pubKey);
mFromPubKey=theApp->getPubKeyCache().store(mAccountFrom, mFromPubKey);
updateID();
@@ -86,7 +93,7 @@ bool Transaction::sign(LocalAccount::pointer fromLocalAccount)
return false;
}
if( (mAmount==0) || (mSourceLedger==0) || (mAccountTo==0) )
if( (mAmount==0) || (mSourceLedger==0) || !mAccountTo.IsValid() )
{
#ifdef DEBUG
std::cerr << "Bad amount, source ledger, or destination" << std::endl;
@@ -94,7 +101,8 @@ bool Transaction::sign(LocalAccount::pointer fromLocalAccount)
assert(false);
return false;
}
if(mAccountFrom!=fromLocalAccount->getAddress())
if(mAccountFrom.getAccountID()!=fromLocalAccount->getAddress().getAccountID())
{
#ifdef DEBUG
std::cerr << "Source mismatch" << std::endl;
@@ -129,9 +137,11 @@ bool Transaction::checkSign() const
Serializer::pointer Transaction::getRaw(bool prefix) const
{
uint160 toAccountID = mAccountTo.getAccountID();
Serializer::pointer ret=boost::make_shared<Serializer>(77);
if(prefix) ret->add32(0x54584e00u);
ret->add160(mAccountTo);
ret->add160(toAccountID);
ret->add64(mAmount);
ret->add32(mFromAccountSeq);
ret->add32(mSourceLedger);
@@ -174,7 +184,7 @@ bool Transaction::save() const
" VALUES ('";
sql.append(mTransactionID.GetHex());
sql.append("','");
sql.append(mAccountFrom.GetHex());
sql.append(mAccountFrom.humanAccountID());
sql.append("','");
sql.append(boost::lexical_cast<std::string>(mFromAccountSeq));
sql.append("','");
@@ -182,7 +192,7 @@ bool Transaction::save() const
sql.append("','");
sql.append(boost::lexical_cast<std::string>(mIdent));
sql.append("','");
sql.append(mAccountTo.GetHex());
sql.append(mAccountTo.humanAccountID());
sql.append("','");
sql.append(boost::lexical_cast<std::string>(mAmount));
sql.append("','");
@@ -238,10 +248,10 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
}
uint256 trID;
uint160 frID, tID;
NewcoinAddress frID, tID;
trID.SetHex(transID);
frID.SetHex(fromID);
tID.SetHex(toID);
frID.setAccountID(fromID);
tID.setAccountID(toID);
CKey::pointer pubkey=theApp->getPubKeyCache().locate(frID);
if(!pubkey) return Transaction::pointer();
@@ -269,10 +279,10 @@ Transaction::pointer Transaction::load(const uint256& id)
return transactionFromSQL(sql);
}
Transaction::pointer Transaction::findFrom(const uint160& fromID, uint32 seq)
Transaction::pointer Transaction::findFrom(const NewcoinAddress& fromID, uint32 seq)
{
std::string sql="SELECT * FROM Transactions WHERE FromID='";
sql.append(fromID.GetHex());
sql.append(fromID.humanAccountID());
sql.append("' AND FromSeq='");
sql.append(boost::lexical_cast<std::string>(seq));
sql.append("';");
@@ -361,13 +371,14 @@ Json::Value Transaction::getJson(bool decorate, bool paid, bool credited) const
}
Json::Value source(Json::objectValue);
source["AccountID"]=NewcoinAddress(mAccountFrom).GetString();
source["AccountID"]=mAccountFrom.humanAccountID();
source["AccountSeq"]=mFromAccountSeq;
source["Ledger"]=mSourceLedger;
if(!!mIdent) source["Identifier"]=mIdent;
Json::Value destination(Json::objectValue);
destination["AccountID"]=NewcoinAddress(mAccountTo).GetString();
destination["AccountID"]=mAccountTo.humanAccountID();
if(decorate)
{

View File

@@ -44,7 +44,7 @@ public:
private:
uint256 mTransactionID;
uint160 mAccountFrom, mAccountTo;
NewcoinAddress mAccountFrom, mAccountTo;
uint64 mAmount, mFee;
uint32 mFromAccountSeq, mSourceLedger, mIdent;
CKey::pointer mFromPubKey;
@@ -56,7 +56,7 @@ private:
public:
Transaction();
Transaction(const std::vector<unsigned char>& rawTransaction, bool validate);
Transaction(LocalAccount::pointer fromLocal, const uint160& to, uint64 amount, uint32 ident, uint32 ledger);
Transaction(LocalAccount::pointer fromLocal, const NewcoinAddress& to, uint64 amount, uint32 ident, uint32 ledger);
bool sign(LocalAccount::pointer fromLocalAccount);
bool checkSign() const;
@@ -67,8 +67,8 @@ public:
Serializer::pointer getSigned() const;
const uint256& getID() const { return mTransactionID; }
const uint160& getFromAccount() const { return mAccountFrom; }
const uint160& getToAccount() const { return mAccountTo; }
const NewcoinAddress& getFromAccount() const { return mAccountFrom; }
const NewcoinAddress& getToAccount() const { return mAccountTo; }
uint64 getAmount() const { return mAmount; }
uint64 getFee() const { return mFee; }
uint32 getFromAccountSeq() const { return mFromAccountSeq; }
@@ -85,7 +85,7 @@ public:
static void saveTransaction(Transaction::pointer);
bool save() const;
static Transaction::pointer load(const uint256& id);
static Transaction::pointer findFrom(const uint160& fromID, uint32 seq);
static Transaction::pointer findFrom(const NewcoinAddress& fromID, uint32 seq);
// conversion function
static bool convertToTransactions(uint32 ourLedgerSeq, uint32 otherLedgerSeq,
@@ -105,7 +105,7 @@ public:
protected:
static Transaction::pointer transactionFromSQL(const std::string& statement);
Transaction(const uint256& transactionID, const uint160& accountFrom, const uint160& accountTo,
Transaction(const uint256& transactionID, const NewcoinAddress& accountFrom, const NewcoinAddress& accountTo,
CKey::pointer key, uint64 amount, uint64 fee, uint32 fromAccountSeq, uint32 sourceLedger,
uint32 ident, const std::vector<unsigned char>& signature, uint32 inLedger, TransStatus status) :
mTransactionID(transactionID), mAccountFrom(accountFrom), mAccountTo(accountTo),
@@ -116,3 +116,4 @@ protected:
};
#endif
// vim:ts=4

View File

@@ -2,31 +2,40 @@
#include "Application.h"
#include "Conversion.h"
void UniqueNodeList::addNode(uint160& hanko, std::vector<unsigned char>& publicKey)
void UniqueNodeList::addNode(NewcoinAddress address,std::string comment)
{
Database* db=theApp->getNetNodeDB()->getDB();
std::string sql="INSERT INTO UNL (Hanko,PubKey) values (";
std::string hashStr;
db->escape(hanko.begin(), hanko.GetSerializeSize(), hashStr);
sql.append(hashStr);
Database* db=theApp->getWalletDB()->getDB();
// void UniqueNodeList::addNode(uint160& hanko, std::vector<unsigned char>& publicKey,std::string comment)
std::string hanko = address.humanHanko();
std::string publicKey = address.humanNodePublic();
std::string sql="INSERT INTO TrustedNodes (Hanko,PubKey,Comment) values (";
std::string tmpStr;
db->escape(reinterpret_cast<const unsigned char*>(hanko.c_str()), hanko.size(), tmpStr);
sql.append(tmpStr);
sql.append(",");
db->escape(&(publicKey[0]), publicKey.size(), hashStr);
sql.append(hashStr);
db->escape(reinterpret_cast<const unsigned char*>(publicKey.c_str()), publicKey.size(), tmpStr);
sql.append(tmpStr);
sql.append(",");
db->escape(reinterpret_cast<const unsigned char*>(comment.c_str()), comment.size(), tmpStr);
sql.append(tmpStr);
sql.append(")");
ScopedLock sl(theApp->getNetNodeDB()->getDBLock());
ScopedLock sl(theApp->getWalletDB()->getDBLock());
db->executeSQL(sql.c_str());
}
void UniqueNodeList::removeNode(uint160& hanko)
{
Database* db=theApp->getNetNodeDB()->getDB();
std::string sql="DELETE FROM UNL where hanko=";
Database* db=theApp->getWalletDB()->getDB();
std::string sql="DELETE FROM TrustedNodes where hanko=";
std::string hashStr;
db->escape(hanko.begin(), hanko.GetSerializeSize(), hashStr);
sql.append(hashStr);
ScopedLock sl(theApp->getNetNodeDB()->getDBLock());
ScopedLock sl(theApp->getWalletDB()->getDBLock());
db->executeSQL(sql.c_str());
}
@@ -34,13 +43,13 @@ void UniqueNodeList::removeNode(uint160& hanko)
#if 0
int UniqueNodeList::checkValid(newcoin::Validation& valid)
{
Database* db=theApp->getNetNodeDB()->getDB();
std::string sql="SELECT pubkey from UNL where hanko=";
Database* db=theApp->getWalletDB()->getDB();
std::string sql="SELECT pubkey from TrustedNodes where hanko=";
std::string hashStr;
db->escape((unsigned char*) &(valid.hanko()[0]),valid.hanko().size(),hashStr);
sql.append(hashStr);
ScopedLock sl(theApp->getNetNodeDB()->getDBLock());
ScopedLock sl(theApp->getWalletDB()->getDBLock());
if( db->executeSQL(sql.c_str()) )
{
if(db->startIterRows() && db->getNextRow())
@@ -59,10 +68,12 @@ int UniqueNodeList::checkValid(newcoin::Validation& valid)
void UniqueNodeList::dumpUNL(std::string& retStr)
{
Database* db=theApp->getNetNodeDB()->getDB();
std::string sql="SELECT * FROM UNL;";
Database* db=theApp->getWalletDB()->getDB();
std::string sql="SELECT * FROM TrustedNodes;";
ScopedLock sl(theApp->getNetNodeDB()->getDBLock());
retStr.append("hello\n");
ScopedLock sl(theApp->getWalletDB()->getDBLock());
if( db->executeSQL(sql.c_str()) )
{
db->startIterRows();

View File

@@ -2,6 +2,7 @@
#define __UNIQUE_NODE_LIST__
#include "../obj/src/newcoin.pb.h"
#include "uint256.h"
#include "NewcoinAddress.h"
class UniqueNodeList
{
@@ -11,15 +12,13 @@ public:
//void load();
//void save();
void addNode(uint160& hanko,std::vector<unsigned char>& publicKey);
void addNode(NewcoinAddress address,std::string comment);
void removeNode(uint160& hanko);
// 0- we don't care, 1- we care and is valid, 2-invalid signature
// int checkValid(newcoin::Validation& valid);
void dumpUNL(std::string& retStr);
};
#endif

View File

@@ -1,6 +1,5 @@
#include "ValidationCollection.h"
#include "Application.h"
#include "NewcoinAddress.h"
#include "Config.h"
#include "Conversion.h"
#include "Application.h"

View File

@@ -21,38 +21,34 @@
#define CHECK_NEW_FAMILIES 500
#endif
//
// LocalAccount - an account
//
LocalAccount::LocalAccount(boost::shared_ptr<LocalAccountFamily> family, int familySeq) :
mPublicKey(family->getPublicKey(familySeq)), mFamily(family), mAccountFSeq(familySeq),
mLgrBalance(0), mTxnDelta(0), mTxnSeq(0)
{
mAcctID=mPublicKey->GetAddress().GetHash160();
mAcctID=mPublicKey->GetAddress();
if(theApp!=NULL) mPublicKey=theApp->getPubKeyCache().store(mAcctID, mPublicKey);
}
std::string LocalAccount::getAccountName() const
{
return mPublicKey->GetAddress().GetString();
}
//
// LocalAccountFamily - a sequences of accounts
//
std::string LocalAccount::getLocalAccountName() const
{
return NewcoinAddress(mFamily->getFamily()).GetString() + ":" + boost::lexical_cast<std::string>(mAccountFSeq);
}
LocalAccountFamily::LocalAccountFamily(const uint160& family, const EC_GROUP* group, const EC_POINT* pubKey) :
LocalAccountFamily::LocalAccountFamily(const NewcoinAddress& family) :
mFamily(family), mLastSeq(0), mRootPrivateKey(NULL)
{
mRootPubKey=EC_POINT_dup(pubKey, group);
mName=family.GetHex().substr(0, 4);
}
LocalAccountFamily::~LocalAccountFamily()
{
lock();
if(mRootPubKey!=NULL) EC_POINT_free(mRootPubKey);
}
uint160 LocalAccountFamily::getAccount(int seq, bool keep)
NewcoinAddress LocalAccountFamily::getAccount(int seq, bool keep)
{
std::map<int, LocalAccount::pointer>::iterator ait=mAccounts.find(seq);
if(ait!=mAccounts.end()) return ait->second->getAddress();
@@ -63,15 +59,15 @@ uint160 LocalAccountFamily::getAccount(int seq, bool keep)
return lae->getAddress();
}
void LocalAccountFamily::unlock(const BIGNUM* privateKey)
void LocalAccountFamily::unlock(BIGNUM* privateKey)
{
if(mRootPrivateKey==NULL) mRootPrivateKey=BN_dup(privateKey);
if(mRootPrivateKey==NULL) mRootPrivateKey=privateKey;
#ifdef CHECK_NEW_FAMILIES
std::cerr << "CheckingFamily" << std::endl;
for(int i=0; i<CHECK_NEW_FAMILIES; i++)
{
EC_KEY *pubkey=CKey::GeneratePublicDeterministicKey(mFamily, mRootPubKey, i);
EC_KEY *pubkey=CKey::GeneratePublicDeterministicKey(mFamily, i);
EC_KEY *privkey=CKey::GeneratePrivateDeterministicKey(mFamily, mRootPrivateKey, i);
int cmp=EC_POINT_cmp(EC_KEY_get0_group(pubkey), EC_KEY_get0_public_key(pubkey),
@@ -79,7 +75,7 @@ void LocalAccountFamily::unlock(const BIGNUM* privateKey)
if(cmp!=0)
{
std::cerr << BN_bn2hex(mRootPrivateKey) << std::endl;
std::cerr << "family=" << mFamily.GetHex() << std::endl;
std::cerr << "family=" << mFamily.humanFamilyGenerator() << std::endl;
std::cerr << "i=" << i << std::endl;
std::cerr << "Key mismatch" << std::endl;
assert(false);
@@ -102,61 +98,32 @@ void LocalAccountFamily::lock()
CKey::pointer LocalAccountFamily::getPublicKey(int seq)
{
return boost::make_shared<CKey>(mFamily, mRootPubKey, seq);
return boost::make_shared<CKey>(mFamily, seq);
}
CKey::pointer LocalAccountFamily::getPrivateKey(int seq)
{
if(!mRootPrivateKey) return CKey::pointer();
std::cerr << "PrivKey(" << mFamily.GetHex() << "," << seq << ")" << std::endl;
std::cerr << "PrivKey(" << mFamily.humanFamilyGenerator() << "," << seq << ")" << std::endl;
return boost::make_shared<CKey>(mFamily, mRootPrivateKey, seq);
}
std::string LocalAccountFamily::getPubGenHex() 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;
}
static bool isHex(char j)
{
if((j>='0') && (j<='9')) return true;
if((j>='A') && (j<='F')) return true;
if((j>='a') && (j<='f')) return true;
return false;
}
Json::Value LocalAccountFamily::getJson() const
{
Json::Value ret(Json::objectValue);
ret["ShortName"]=getShortName();
ret["FullName"]=getFamily().GetHex();
ret["PublicGenerator"]=getPubGenHex();
ret["FullName"]=getFamily().humanFamilyGenerator();
ret["IsLocked"]=isLocked();
if(!getComment().empty()) ret["Comment"]=getComment();
return ret;
}
LocalAccountFamily::pointer LocalAccountFamily::readFamily(const uint160& family)
LocalAccountFamily::pointer LocalAccountFamily::readFamily(const NewcoinAddress& family)
{
std::string sql="SELECT * from LocalAcctFamilies WHERE FamilyName='";
sql.append(family.GetHex());
std::string sql="SELECT * from LocalAcctFamilies WHERE FamilyGenerator='";
sql.append(family.humanFamilyGenerator());
sql.append("';");
std::string rootPubKey, name, comment;
std::string comment;
uint32 seq;
if(1)
@@ -167,57 +134,39 @@ LocalAccountFamily::pointer LocalAccountFamily::readFamily(const uint160& family
if(!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
return LocalAccountFamily::pointer();
db->getStr("RootPubKey", rootPubKey);
db->getStr("Name", name);
db->getStr("Comment", comment);
seq=db->getBigInt("Seq");
db->endIterRows();
}
EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
if(!grp) return LocalAccountFamily::pointer();
LocalAccountFamily::pointer fam=boost::make_shared<LocalAccountFamily>(family);
EC_POINT *pubKey=EC_POINT_hex2point(grp, rootPubKey.c_str(), NULL, NULL);
if(!pubKey)
{
EC_GROUP_free(grp);
assert(false);
return LocalAccountFamily::pointer();
}
LocalAccountFamily::pointer fam=boost::make_shared<LocalAccountFamily>(family, grp, pubKey);
EC_GROUP_free(grp);
EC_POINT_free(pubKey);
fam->setName(name);
fam->setComment(comment);
fam->setSeq(seq);
return fam;
}
void LocalAccountFamily::write(bool is_new)
{
std::string sql="INSERT INTO LocalAcctFamilies (FamilyName,RootPubKey,Seq,Name,Comment) VALUES ('";
sql.append(mFamily.GetHex());
std::string sql="INSERT INTO LocalAcctFamilies (FamilyGenerator,Seq,Comment) VALUES ('";
sql.append(mFamily.humanFamilyGenerator());
sql.append("','");
EC_GROUP* grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
if(!grp) return;
char *rpk=EC_POINT_point2hex(grp, mRootPubKey, POINT_CONVERSION_COMPRESSED, NULL);
EC_GROUP_free(grp);
if(!rpk) return;
sql.append(rpk);
OPENSSL_free(rpk);
// EC_GROUP* grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
// if(!grp) return;
// char *rpk=EC_POINT_point2hex(grp, mRootPubKey, POINT_CONVERSION_COMPRESSED, NULL);
// EC_GROUP_free(grp);
// if(!rpk) return;
// sql.append(rpk);
// OPENSSL_free(rpk);
// sql.append("','");
sql.append("','");
sql.append(boost::lexical_cast<std::string>(mLastSeq));
sql.append("',");
std::string f;
theApp->getWalletDB()->getDB()->escape((const unsigned char *) mName.c_str(), mName.size(), f);
sql.append(f);
sql.append(",");
theApp->getWalletDB()->getDB()->escape((const unsigned char *) mComment.c_str(), mComment.size(), f);
sql.append(f);
@@ -227,67 +176,20 @@ void LocalAccountFamily::write(bool is_new)
theApp->getWalletDB()->getDB()->executeSQL(sql.c_str());
}
bool Wallet::isHexPrivateKey(const std::string& s)
{ // 65 characters, first is 'P', rest are all legal hex
if(s.size()!=65) return false;
if(s[0]!='P') return false;
for(int i=1; i<65; i++)
if(!isHex(s[i])) return false;
return true;
}
bool Wallet::isHexPublicKey(const std::string& s)
{ // 66 characters, all legal hex, starts with '02' or '03'
if(s.size()!=66) return false;
if(s[0]!='0') return false;
if((s[1]!='2') && (s[1]!='3')) return false;
for(int i=3; i<66; i++)
if(!isHex(s[i])) return false;
return true;
}
bool Wallet::isHexFamily(const std::string& s)
{ // 64 characters, all legal hex
if(s.size()!=64) return false;
for(int i=0; i<64; i++)
if(!isHex(s[i])) return false;
return true;
}
std::string Wallet::privKeyToText(const uint256& privKey)
{
std::string ret("P");
ret.append(privKey.GetHex());
return ret;
}
uint256 Wallet::textToPrivKey(const std::string& privKey)
{
uint256 ret;
if((privKey.length()==65) && (privKey[0]=='P'))
ret.SetHex(privKey.c_str()+1);
return ret;
}
std::string LocalAccountFamily::getSQLFields()
{
return "(FamilyName,RootPubKey,Seq,Name,Comment)";
return "(FamilyGenerator,Seq,Comment)";
}
std::string LocalAccountFamily::getSQL() const
{ // familyname(40), pubkey(66), seq, name, comment
{ // familyname(40), seq, comment
std::string ret("('");
ret.append(mFamily.GetHex());
ret+="','";
ret.append(getPubGenHex());
ret.append(mFamily.humanFamilyGenerator());
ret.append("','");
ret.append(boost::lexical_cast<std::string>(mLastSeq));
ret.append("',");
std::string esc;
theApp->getWalletDB()->getDB()->escape((const unsigned char *) mName.c_str(), mName.size(), esc);
ret.append(esc);
ret.append(",");
theApp->getWalletDB()->getDB()->escape((const unsigned char *) mComment.c_str(), mComment.size(), esc);
ret.append(esc);
@@ -302,71 +204,58 @@ LocalAccount::pointer LocalAccountFamily::get(int seq)
LocalAccount::pointer ret=boost::make_shared<LocalAccount>(shared_from_this(), seq);
mAccounts.insert(std::make_pair(seq, ret));
return ret;
}
uint160 Wallet::findFamilySN(const std::string& shortName)
{ // OPTIMIZEME
boost::recursive_mutex::scoped_lock sl(mLock);
for(std::map<uint160, LocalAccountFamily::pointer>::iterator it=mFamilies.begin();
it!=mFamilies.end(); ++it)
NewcoinAddress Wallet::addFamily(const NewcoinAddress& familySeed, bool lock)
{
if(it->second->getShortName()==shortName)
return it->first;
}
return 0;
LocalAccountFamily::pointer fam(doPrivate(familySeed, true, !lock));
return fam ? fam->getFamily() : NewcoinAddress();
}
uint160 Wallet::addFamily(const uint256& key, bool lock)
// Create a family. Return the family public generator and the seed.
NewcoinAddress Wallet::addRandomFamily(NewcoinAddress& familySeed)
{
LocalAccountFamily::pointer fam(doPrivate(key, true, !lock));
if(!fam) return uint160();
return fam->getFamily();
}
uint128 key;
uint160 Wallet::addRandomFamily(uint256& key)
{
RAND_bytes((unsigned char *) &key, sizeof(key));
return addFamily(key, false);
familySeed.setFamilySeed(key);
return addFamily(familySeed, false);
}
uint160 Wallet::addFamily(const std::string& payPhrase, bool lock)
NewcoinAddress Wallet::addFamily(const std::string& payPhrase, bool lock)
{
return addFamily(CKey::PassPhraseToKey(payPhrase), lock);
NewcoinAddress familySeed;
familySeed.setFamilySeed(CKey::PassPhraseToKey(payPhrase));
return addFamily(familySeed, lock);
}
uint160 Wallet::addFamily(const std::string& pubKey)
NewcoinAddress Wallet::addFamily(const NewcoinAddress& familyGenerator)
{
LocalAccountFamily::pointer fam(doPublic(pubKey, true, true));
if(!fam) return uint160();
return fam->getFamily();
LocalAccountFamily::pointer fam(doPublic(familyGenerator, true, true));
return fam ? fam->getFamily() : NewcoinAddress();
}
uint160 Wallet::findFamilyPK(const std::string& pubKey)
NewcoinAddress Wallet::findFamilyPK(const NewcoinAddress& familyGenerator)
{
LocalAccountFamily::pointer fam(doPublic(pubKey, false, true));
if(!fam) return uint160();
return fam->getFamily();
}
LocalAccountFamily::pointer fam(doPublic(familyGenerator, false, true));
std::string LocalAccount::getShortName() const
{
std::string ret, cmt;
if(!theApp->getWallet().getFamilyInfo(mFamily->getFamily(), ret, cmt))
ret=mFamily->getFamily().GetHex();
ret.append(":");
if(mName.empty())
ret.append(boost::lexical_cast<std::string>(mAccountFSeq));
else ret.append(mName);
return ret;
return fam ? fam->getFamily() : NewcoinAddress();
}
std::string LocalAccount::getFullName() const
{
std::string ret(mFamily->getFamily().GetHex());
std::string ret(mFamily->getFamily().humanFamilyGenerator());
ret.append(":");
ret.append(boost::lexical_cast<std::string>(mAccountFSeq));
return ret;
}
@@ -377,15 +266,14 @@ bool LocalAccount::isLocked() const
std::string LocalAccount::getFamilyName() const
{
return mFamily->getShortName();
return mFamily->getFamily().humanFamilyGenerator();
}
Json::Value LocalAccount::getJson() const
{
Json::Value ret(Json::objectValue);
ret["Family"]=getFamilyName();
ret["AccountID"]=NewcoinAddress(getAddress()).GetString();
ret["ShortName"]=getShortName();
ret["AccountID"]=getAddress().humanAccountID();
ret["FullName"]=getFullName();
ret["Issued"]=Json::Value(isIssued());
ret["IsLocked"]=mFamily->isLocked();
@@ -409,43 +297,49 @@ CKey::pointer LocalAccount::getPrivateKey()
return mFamily->getPrivateKey(mAccountFSeq);
}
void Wallet::getFamilies(std::vector<uint160>& familyIDs)
void Wallet::getFamilies(std::vector<NewcoinAddress>& familyIDs)
{
boost::recursive_mutex::scoped_lock sl(mLock);
familyIDs.reserve(mFamilies.size());
for(std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.begin(); fit!=mFamilies.end(); ++fit)
for(std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.begin(); fit!=mFamilies.end(); ++fit)
familyIDs.push_back(fit->first);
}
bool Wallet::getFamilyInfo(const uint160& family, std::string& name, std::string& comment)
// Look up a family in the wallet.
bool Wallet::getFamilyInfo(const NewcoinAddress& family, std::string& comment)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit==mFamilies.end()) return false;
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit==mFamilies.end())
return false;
assert(fit->second->getFamily()==family);
name=fit->second->getShortName();
comment=fit->second->getComment();
return true;
}
bool Wallet::getFullFamilyInfo(const uint160& family, std::string& name, std::string& comment,
#if 0
bool Wallet::getFullFamilyInfo(const NewcoinAddress& family, std::string& comment,
std::string& pubGen, bool& isLocked)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit==mFamilies.end()) return false;
assert(fit->second->getFamily()==family);
name=fit->second->getShortName();
comment=fit->second->getComment();
pubGen=fit->second->getPubGenHex();
isLocked=fit->second->isLocked();
return true;
}
#endif
Json::Value Wallet::getFamilyJson(const uint160& family)
Json::Value Wallet::getFamilyJson(const NewcoinAddress& family)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit==mFamilies.end()) return Json::Value(Json::nullValue);
assert(fit->second->getFamily()==family);
return fit->second->getJson();
@@ -467,22 +361,21 @@ void Wallet::load()
if(!db->startIterRows()) return;
while(db->getNextRow())
{
std::string family, rootpub, name, comment;
db->getStr("FamilyName", family);
db->getStr("RootPubKey", rootpub);
db->getStr("Name", name);
std::string familyGenerator, comment;
db->getStr("FamilyGenerator", familyGenerator);
db->getStr("Comment", comment);
int seq=db->getBigInt("Seq");
uint160 fb;
fb.SetHex(family);
NewcoinAddress family;
LocalAccountFamily::pointer f(doPublic(rootpub, true, false));
family.setFamilyGenerator(familyGenerator);
LocalAccountFamily::pointer f(doPublic(family, true, false));
if(f)
{
assert(f->getFamily()==fb);
// XXX Compare could be better.
assert(f->getFamily().getFamilyGenerator()==family.getFamilyGenerator());
f->setSeq(seq);
f->setName(name);
f->setComment(comment);
}
else assert(false);
@@ -490,35 +383,18 @@ void Wallet::load()
db->endIterRows();
}
std::string Wallet::getPubGenHex(const uint160& famBase)
// YYY Perhaps this should take a comment.
LocalAccount::pointer Wallet::getNewLocalAccount(const NewcoinAddress& family)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(famBase);
if(fit==mFamilies.end()) return "";
assert(fit->second->getFamily()==famBase);
return fit->second->getPubGenHex();
}
std::string Wallet::getShortName(const uint160& famBase)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(famBase);
if(fit==mFamilies.end()) return "";
assert(fit->second->getFamily()==famBase);
return fit->second->getShortName();
}
LocalAccount::pointer Wallet::getNewLocalAccount(const uint160& family)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit==mFamilies.end()) return LocalAccount::pointer();
uint32 seq=fit->second->getSeq();
uint160 acct=fit->second->getAccount(seq, true);
NewcoinAddress acct=fit->second->getAccount(seq, true);
fit->second->setSeq(seq+1); // FIXME: writeout new seq
std::map<uint160, LocalAccount::pointer>::iterator ait=mAccounts.find(acct);
std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait=mAccounts.find(acct);
if(ait!=mAccounts.end()) return ait->second;
LocalAccount::pointer lac=boost::make_shared<LocalAccount>(fit->second, seq);
@@ -526,17 +402,19 @@ LocalAccount::pointer Wallet::getNewLocalAccount(const uint160& family)
sl.unlock();
lac->syncLedger();
return lac;
}
LocalAccount::pointer Wallet::getLocalAccount(const uint160& family, int seq)
LocalAccount::pointer Wallet::getLocalAccount(const NewcoinAddress& family, int seq)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit==mFamilies.end()) return LocalAccount::pointer();
uint160 acct=fit->second->getAccount(seq, true);
std::map<uint160, LocalAccount::pointer>::iterator ait=mAccounts.find(acct);
NewcoinAddress acct=fit->second->getAccount(seq, true);
std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait=mAccounts.find(acct);
if(ait!=mAccounts.end()) return ait->second;
LocalAccount::pointer lac=boost::make_shared<LocalAccount>(fit->second, seq);
@@ -544,13 +422,14 @@ LocalAccount::pointer Wallet::getLocalAccount(const uint160& family, int seq)
sl.unlock();
lac->syncLedger();
return lac;
}
LocalAccount::pointer Wallet::getLocalAccount(const uint160& acctID)
LocalAccount::pointer Wallet::getLocalAccount(const NewcoinAddress& acctID)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccount::pointer>::iterator ait=mAccounts.find(acctID);
std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait=mAccounts.find(acctID);
if(ait==mAccounts.end()) return LocalAccount::pointer();
return ait->second;
}
@@ -558,7 +437,7 @@ LocalAccount::pointer Wallet::getLocalAccount(const uint160& acctID)
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)
for(std::map<NewcoinAddress, LocalAccount::pointer>::iterator it=mAccounts.begin(); it!=mAccounts.end(); ++it)
if(!it->second->isLocked() && (it->second->getEffectiveBalance()>=amount) )
return it->second;
return LocalAccount::pointer();
@@ -566,49 +445,64 @@ LocalAccount::pointer Wallet::findAccountForTransaction(uint64 amount)
LocalAccount::pointer Wallet::parseAccount(const std::string& specifier)
{ // <family>:<seq> or <acct_id>
std::cerr << "Parse(" << specifier << ")" << std::endl;
size_t colon=specifier.find(':');
if(colon == std::string::npos)
{
std::cerr << "nocolon" << std::endl;
NewcoinAddress na(specifier);
if(!na.IsValid()) return LocalAccount::pointer();
return getLocalAccount(na.GetHash160());
NewcoinAddress na;
if (na.setAccountID(specifier))
{
return getLocalAccount(na);
}
else
{
return LocalAccount::pointer();
}
}
if (colon==0) return LocalAccount::pointer();
std::string family=specifier.substr(0, colon);
std::string seq=specifier.substr(colon+1);
if(seq.empty()) return LocalAccount::pointer();
std::cerr << "family(" << family << "), seq(" << seq << ")" << std::endl;
uint160 f;
if(isHexFamily(family))
f.SetHex(family);
else if(isHexPublicKey(family))
f=findFamilyPK(family);
else
f=findFamilySN(family);
if(!f) return LocalAccount::pointer();
return getLocalAccount(f, boost::lexical_cast<int>(seq));
NewcoinAddress familyParsed;
NewcoinAddress familyFound;
if (familyParsed.setFamilyGenerator(family))
{
familyFound = findFamilyPK(familyParsed);
}
if (familyParsed.setFamilySeed(family))
{
// XXX Was private generator, should derive public generator.
; // nothing
}
uint160 Wallet::peekKey(const uint160& family, int seq)
return familyFound.IsValid()
? getLocalAccount(familyFound, boost::lexical_cast<int>(seq))
: LocalAccount::pointer();
}
NewcoinAddress Wallet::peekKey(const NewcoinAddress& family, int seq)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit==mFamilies.end()) return uint160();
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit==mFamilies.end()) return NewcoinAddress();
return fit->second->getAccount(seq, false);
}
void Wallet::delFamily(const uint160& familyName)
void Wallet::delFamily(const NewcoinAddress& familyName)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(familyName);
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(familyName);
if(fit==mFamilies.end()) return;
std::map<int, LocalAccount::pointer>& acctMap=fit->second->getAcctMap();
@@ -618,10 +512,13 @@ void Wallet::delFamily(const uint160& familyName)
mFamilies.erase(familyName);
}
LocalAccountFamily::pointer Wallet::doPublic(const std::string& pubKey, bool do_create, bool do_db)
// --> pubKey: hex
// --> do_create: Add to mFamilies
// --> do_db: write out db
LocalAccountFamily::pointer Wallet::doPublic(const NewcoinAddress& pubKey, bool do_create, bool do_db)
{
// Generate root key
EC_KEY *pkey=CKey::GenerateRootPubKey(pubKey);
EC_KEY *pkey=CKey::GenerateRootPubKey(pubKey.getFamilyGeneratorBN());
if(!pkey)
{
#ifdef DEBUG
@@ -636,10 +533,12 @@ LocalAccountFamily::pointer Wallet::doPublic(const std::string& pubKey, bool do_
unsigned char *begin=&rootPubKey[0];
i2o_ECPublicKey(pkey, &begin);
while(rootPubKey.size()<33) rootPubKey.push_back((unsigned char)0);
uint160 family=NewcoinAddress(rootPubKey).GetHash160();
NewcoinAddress family;
family.setFamilyGenerator(rootPubKey);
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit!=mFamilies.end()) // already added
{
EC_KEY_free(pkey);
@@ -657,9 +556,10 @@ LocalAccountFamily::pointer Wallet::doPublic(const std::string& pubKey, bool do_
fam=LocalAccountFamily::readFamily(family);
if(fam) do_create=false;
}
if(do_create)
{
fam=boost::make_shared<LocalAccountFamily>(family, EC_KEY_get0_group(pkey), EC_KEY_get0_public_key(pkey));
fam=boost::make_shared<LocalAccountFamily>(family);
mFamilies.insert(std::make_pair(family, fam));
if(do_db) fam->write(true);
}
@@ -669,21 +569,14 @@ LocalAccountFamily::pointer Wallet::doPublic(const std::string& pubKey, bool do_
return fam;
}
LocalAccountFamily::pointer Wallet::doPrivate(const uint256& passPhrase, bool do_create, bool do_unlock)
LocalAccountFamily::pointer Wallet::doPrivate(const NewcoinAddress& familySeed, bool do_create, bool do_unlock)
{
// Generate root key
EC_KEY *base=CKey::GenerateRootDeterministicKey(passPhrase);
// Extract family name
std::vector<unsigned char> rootPubKey(33, 0);
unsigned char *begin=&rootPubKey[0];
i2o_ECPublicKey(base, &begin);
while(rootPubKey.size()<33) rootPubKey.push_back((unsigned char)0);
uint160 family=NewcoinAddress(rootPubKey).GetHash160();
NewcoinAddress family;
family.setFamilyGenerator(familySeed);
boost::recursive_mutex::scoped_lock sl(mLock);
LocalAccountFamily::pointer fam;
std::map<uint160, LocalAccountFamily::pointer>::iterator it=mFamilies.find(family);
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator it=mFamilies.find(family);
if(it==mFamilies.end())
{ // family not found
fam=LocalAccountFamily::readFamily(family);
@@ -691,11 +584,9 @@ LocalAccountFamily::pointer Wallet::doPrivate(const uint256& passPhrase, bool do
{
if(!do_create)
{
EC_KEY_free(base);
return LocalAccountFamily::pointer();
}
fam=boost::make_shared<LocalAccountFamily>(family,
EC_KEY_get0_group(base), EC_KEY_get0_public_key(base));
fam=boost::make_shared<LocalAccountFamily>(family);
mFamilies.insert(std::make_pair(family, fam));
fam->write(true);
}
@@ -703,17 +594,17 @@ LocalAccountFamily::pointer Wallet::doPrivate(const uint256& passPhrase, bool do
else fam=it->second;
if(do_unlock && fam->isLocked())
fam->unlock(EC_KEY_get0_private_key(base));
fam->unlock(familySeed.getFamilyPrivateKey());
sl.unlock();
EC_KEY_free(base);
return fam;
}
bool Wallet::lock(const uint160& family)
bool Wallet::lock(const NewcoinAddress& family)
{
boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
if(fit==mFamilies.end()) return false;
fit->second->lock();
return true;
@@ -722,13 +613,14 @@ bool Wallet::lock(const uint160& family)
void Wallet::lock()
{
boost::recursive_mutex::scoped_lock sl(mLock);
for(std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.begin();
for(std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.begin();
fit!=mFamilies.end(); ++fit)
fit->second->lock();
}
bool Wallet::unitTest()
{ // Create 100 keys for each of 1,000 families and ensure all keys match
#if 0
Wallet pub, priv;
uint256 privBase(time(NULL)^(getpid()<<16));
@@ -736,12 +628,13 @@ bool Wallet::unitTest()
for(int i=0; i<1000; i++, privBase++)
{
uint160 fam=priv.addFamily(privBase, false);
NewcoinAddress fam=priv.addFamily(privBase, false);
#ifdef DEBUG
std::cerr << "Priv: " << privBase.GetHex() << " Fam: " << fam.GetHex() << std::endl;
#endif
#if 0
std::string pubGen=priv.getPubGenHex(fam);
#ifdef DEBUG
std::cerr << "Pub: " << pubGen << std::endl;
@@ -764,7 +657,7 @@ bool Wallet::unitTest()
assert(false);
return false;
}
#endif
for(int j=0; j<100; j++)
{
LocalAccount::pointer lpub=pub.getLocalAccount(fam, j);
@@ -774,8 +667,8 @@ bool Wallet::unitTest()
assert(false);
return false;
}
uint160 lpuba=lpub->getAddress();
uint160 lpriva=lpriv->getAddress();
NewcoinAddress lpuba=lpub->getAddress();
NewcoinAddress lpriva=lpriv->getAddress();
#ifdef DEBUG
// std::cerr << "pubA(" << j << "): " << lpuba.GetHex() << std::endl;
// std::cerr << "prvA(" << j << "): " << lpriva.GetHex() << std::endl;
@@ -793,6 +686,7 @@ bool Wallet::unitTest()
priv.delFamily(fam);
}
#endif
return true;
}
@@ -805,7 +699,7 @@ void Wallet::syncToLedger(bool force, Ledger* ledger)
{ // check each transaction, see if it's in the ledger or allowed in the ledger
// WRITEME
}
for(std::map<uint160, LocalAccount::pointer>::iterator ait=mAccounts.begin(); ait!=mAccounts.end(); ++ait)
for(std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait=mAccounts.begin(); ait!=mAccounts.end(); ++ait)
{ // check each account, see if our ledger balance matches
LocalAccount::pointer& lac=ait->second;
AccountState::pointer acs=ledger->getAccountState(ait->first);
@@ -827,7 +721,7 @@ void Wallet::applyTransaction(Transaction::pointer txn)
std::map<uint256, LocalTransaction::pointer>::iterator lti=mTransactions.find(txn->getID());
if(lti!=mTransactions.end()) ltx=lti->second;
std::map<uint160, LocalAccount::pointer>::iterator lac=mAccounts.find(txn->getToAccount());
std::map<NewcoinAddress, LocalAccount::pointer>::iterator lac=mAccounts.find(txn->getToAccount());
if(lac!=mAccounts.end())
{ // this is to a local account
if(!ltx)
@@ -897,10 +791,11 @@ bool Wallet::getTxJson(const uint256& txn, Json::Value& ret)
std::map<uint256, LocalTransaction::pointer>::iterator it=mTransactions.find(txn);
if(it==mTransactions.end()) return false;
ret=it->second->getJson();
return true;
}
bool Wallet::getTxsJson(const uint160& account, Json::Value& ret)
bool Wallet::getTxsJson(const NewcoinAddress& account, Json::Value& ret)
{
boost::recursive_mutex::scoped_lock sl(mLock);
for(std::map<uint256, LocalTransaction::pointer>::iterator it=mTransactions.begin();
@@ -910,5 +805,7 @@ bool Wallet::getTxsJson(const uint160& account, Json::Value& ret)
if(txn && ((account==txn->getFromAccount())||(account==txn->getToAccount())) )
ret[it->first.GetHex()]=it->second->getJson();
}
return true;
}
// vim:ts=4

View File

@@ -24,35 +24,32 @@ class Wallet
protected:
boost::recursive_mutex mLock;
std::map<uint160, LocalAccountFamily::pointer> mFamilies;
std::map<uint160, LocalAccount::pointer> mAccounts;
std::map<NewcoinAddress, LocalAccountFamily::pointer> mFamilies;
std::map<NewcoinAddress, LocalAccount::pointer> mAccounts;
std::map<uint256, LocalTransaction::pointer> mTransactions;
uint32 mLedger; // ledger we last synched to
LocalAccountFamily::pointer doPrivate(const uint256& passPhrase, bool do_create, bool do_unlock);
LocalAccountFamily::pointer doPublic(const std::string& pubKey, bool do_create, bool do_db);
LocalAccountFamily::pointer doPrivate(const NewcoinAddress& familySeed, bool do_create, bool do_unlock);
LocalAccountFamily::pointer doPublic(const NewcoinAddress& pubKey, bool do_create, bool do_db);
void addFamily(const uint160& family, const std::string& pubKey, int seq,
const std::string& name, const std::string& comment);
// void addFamily(const NewcoinAddress& family, const std::string& pubKey, int seq, const std::string& name, const std::string& comment);
public:
Wallet() : mLedger(0) { ; }
uint160 addFamily(const std::string& passPhrase, bool lock);
uint160 addFamily(const uint256& passPhrase, bool lock);
uint160 addFamily(const std::string& pubKey);
uint160 addRandomFamily(uint256& privKey);
NewcoinAddress addFamily(const std::string& passPhrase, bool lock);
NewcoinAddress addFamily(const NewcoinAddress& familySeed, bool lock);
NewcoinAddress addFamily(const NewcoinAddress& familyGenerator);
NewcoinAddress addRandomFamily(NewcoinAddress& familySeed);
uint160 findFamilySN(const std::string& shortName);
uint160 findFamilyPK(const std::string& pubKey);
NewcoinAddress findFamilyPK(const NewcoinAddress& familyGenerator);
void delFamily(const uint160& familyName);
void delFamily(const NewcoinAddress& familyName);
void getFamilies(std::vector<uint160>& familyIDs);
void getFamilies(std::vector<NewcoinAddress>& familyIDs);
uint160 unlock(const uint256& passPhrase);
bool lock(const uint160& familyName);
bool lock(const NewcoinAddress& familyName);
void lock();
void load();
@@ -60,29 +57,20 @@ public:
// must be a known local account
LocalAccount::pointer parseAccount(const std::string& accountSpecifier);
LocalAccount::pointer getLocalAccount(const uint160& famBase, int seq);
LocalAccount::pointer getLocalAccount(const uint160& acctID);
LocalAccount::pointer getNewLocalAccount(const uint160& family);
LocalAccount::pointer getLocalAccount(const NewcoinAddress& famBase, int seq);
LocalAccount::pointer getLocalAccount(const NewcoinAddress& acctID);
LocalAccount::pointer getNewLocalAccount(const NewcoinAddress& 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);
NewcoinAddress peekKey(const NewcoinAddress& family, int seq);
bool getFamilyInfo(const uint160& family, std::string& name, std::string& comment);
bool getFullFamilyInfo(const uint160& family, std::string& name, std::string& comment,
std::string& pubGen, bool& isLocked);
bool getFamilyInfo(const NewcoinAddress& family, std::string& comment);
// bool getFullFamilyInfo(const NewcoinAddress& family, std::string& comment, std::string& pubGen, bool& isLocked);
Json::Value getFamilyJson(const uint160& family);
Json::Value getFamilyJson(const NewcoinAddress& family);
bool getTxJson(const uint256& txid, Json::Value& value);
bool getTxsJson(const uint160& acctid, Json::Value& value);
bool getTxsJson(const NewcoinAddress& acctid, Json::Value& value);
void addLocalTransactions(Json::Value&);
static bool isHexPrivateKey(const std::string&);
static bool isHexPublicKey(const std::string&);
static bool isHexFamily(const std::string&);
static std::string privKeyToText(const uint256& privKey);
static uint256 textToPrivKey(const std::string&);
void syncToLedger(bool force, Ledger* ledger);
void applyTransaction(Transaction::pointer);

View File

@@ -37,8 +37,7 @@ inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char
std::reverse_copy(pbegin, pend, vchTmp.begin());
// Convert little endian data to bignum
CBigNum bn;
bn.setvch(vchTmp);
CBigNum bn(vchTmp);
// Convert bignum to std::string
std::string str;
@@ -181,6 +180,12 @@ protected:
memset(&vchData[0], 0, vchData.size());
}
void SetData(int nVersionIn, std::vector<unsigned char> vchDataIn)
{
nVersion = nVersionIn;
vchData = vchDataIn;
}
void SetData(int nVersionIn, const void* pdata, size_t nSize)
{
nVersion = nVersionIn;
@@ -195,14 +200,14 @@ protected:
}
public:
bool SetString(const char* psz)
bool SetString(const char* psz, unsigned char version)
{
std::vector<unsigned char> vchTemp;
DecodeBase58Check(psz, vchTemp);
if (vchTemp.empty())
if (vchTemp.empty() || vchTemp[0] != version)
{
vchData.clear();
nVersion = 0;
nVersion = 1;
return false;
}
nVersion = vchTemp[0];
@@ -213,9 +218,9 @@ public:
return true;
}
bool SetString(const std::string& str)
bool SetString(const std::string& str, unsigned char version)
{
return SetString(str.c_str());
return SetString(str.c_str(), version);
}
std::string ToString() const

View File

@@ -123,25 +123,25 @@ public:
}
static uint256 PassPhraseToKey(const std::string& passPhrase);
static EC_KEY* GenerateRootDeterministicKey(const uint256& passPhrase);
static EC_KEY* GenerateRootPubKey(const std::string& pubHex);
static EC_KEY* GeneratePublicDeterministicKey(const uint160& family, const EC_POINT* rootPub, int n);
static EC_KEY* GeneratePrivateDeterministicKey(const uint160& family, const BIGNUM* rootPriv, int n);
static uint128 PassPhraseToKey(const std::string& passPhrase);
static EC_KEY* GenerateRootDeterministicKey(const uint128& passPhrase);
static EC_KEY* GenerateRootPubKey(BIGNUM* pubGenerator);
static EC_KEY* GeneratePublicDeterministicKey(const NewcoinAddress& family, int n);
static EC_KEY* GeneratePrivateDeterministicKey(const NewcoinAddress& family, const BIGNUM* rootPriv, int n);
CKey(const uint256& passPhrase) : fSet(true)
CKey(const uint128& passPhrase) : fSet(true)
{
pkey = GenerateRootDeterministicKey(passPhrase);
assert(pkey);
}
CKey(const uint160& base, const EC_POINT* rootPubKey, int n) : fSet(true)
CKey(const NewcoinAddress& base, int n) : fSet(true)
{ // public deterministic key
pkey = GeneratePublicDeterministicKey(base, rootPubKey, n);
pkey = GeneratePublicDeterministicKey(base, n);
assert(pkey);
}
CKey(const uint160& base, const BIGNUM* rootPrivKey, int n) : fSet(true)
CKey(const NewcoinAddress& base, const BIGNUM* rootPrivKey, int n) : fSet(true)
{ // private deterministic key
pkey = GeneratePrivateDeterministicKey(base, rootPrivKey, n);
assert(pkey);
@@ -271,8 +271,13 @@ public:
NewcoinAddress GetAddress() const
{
return NewcoinAddress(GetPubKey());
NewcoinAddress* ret = new NewcoinAddress();
ret->setAccountPublic(GetPubKey());
return *ret;
}
};
#endif
// vim:ts=4

View File

@@ -14,6 +14,8 @@
#include "types.h"
#include <openssl/bn.h>
#if defined(_MSC_VER) && _MSC_VER < 1300
#define for if (false) ; else for
#endif
@@ -33,6 +35,19 @@ protected:
unsigned int pn[WIDTH];
public:
BIGNUM *toBN() const
{
// Convert to big-endian
unsigned char *be[WIDTH];
unsigned char *bep;
unsigned int *pnp = &pn[WIDTH];
for (int i=WIDTH; i--;)
*bep++ = *--pnp;
return BN_bin2bn(be, WIDTH, NULL);
}
bool isZero() const
{
for (int i = 0; i < WIDTH; i++)
@@ -415,22 +430,64 @@ public:
}
friend class uint128;
friend class uint160;
friend class uint256;
friend inline int Testuint256AdHoc(std::vector<std::string> vArg);
};
typedef base_uint<128> base_uint128;
typedef base_uint<160> base_uint160;
typedef base_uint<256> base_uint256;
//
// uint160 and uint256 could be implemented as templates, but to keep
// uint128, uint160, & uint256 could be implemented as templates, but to keep
// compile errors and debugging cleaner, they're copy and pasted.
//
//////////////////////////////////////////////////////////////////////////////
//
// uint128
//
class uint128 : public base_uint128
{
public:
typedef base_uint128 basetype;
uint128()
{
for (int i = 0; i < WIDTH; i++)
pn[i] = 0;
}
uint128(const basetype& b)
{
for (int i = 0; i < WIDTH; i++)
pn[i] = b.pn[i];
}
uint128& operator=(const basetype& b)
{
for (int i = 0; i < WIDTH; i++)
pn[i] = b.pn[i];
return *this;
}
explicit uint128(const base_uint256 b) {
for (int i = 0; i < WIDTH; i++)
pn[i] = b.pn[i];
}
explicit uint128(const std::vector<unsigned char>& vch)
{
if (vch.size() == sizeof(pn))
memcpy(pn, &vch[0], sizeof(pn));
else
memset(pn, 0, sizeof(pn));
}
};
//////////////////////////////////////////////////////////////////////////////
//
@@ -543,11 +600,6 @@ inline const uint160 operator|(const uint160& a, const uint160& b) { return (b
inline const uint160 operator+(const uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; }
inline const uint160 operator-(const uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; }
//////////////////////////////////////////////////////////////////////////////
//
// uint256
@@ -792,3 +844,4 @@ inline int Testuint256AdHoc(std::vector<std::string> vArg)
}
#endif
// vim:ts=4