diff --git a/SConstruct b/SConstruct index e54fbf31b7..5f6f3897ae 100644 --- a/SConstruct +++ b/SConstruct @@ -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') diff --git a/src/AccountState.cpp b/src/AccountState.cpp index d5612eee42..cc7d92e63b 100644 --- a/src/AccountState.cpp +++ b/src/AccountState.cpp @@ -8,19 +8,21 @@ AccountState::AccountState(const std::vector& 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 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(mBalance); as["SendSequence"]=mAccountSeq; if(!mValid) as["Invalid"]=true; - NewcoinAddress nad(mAccountID); - val[nad.GetString()]=as; + + val[mAccountID.humanAccountID()]=as; } +// vim:ts=4 diff --git a/src/AccountState.h b/src/AccountState.h index c8075dd0b0..5c1b615023 100644 --- a/src/AccountState.h +++ b/src/AccountState.h @@ -11,6 +11,7 @@ #include "types.h" #include "uint256.h" +#include "NewcoinAddress.h" class AccountState { @@ -18,16 +19,16 @@ public: typedef boost::shared_ptr 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&); // 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 diff --git a/src/Application.cpp b/src/Application.cpp index 008ec922a9..2b605d1048 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -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(); diff --git a/src/DBInit.cpp b/src/DBInit.cpp index fc14c4ddcc..6eff69b219 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -49,11 +49,9 @@ 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), \ - Seq BIGINT UNSIGNED, \ - Name TEXT, \ - Comment TEXT \ + FamilyGenerator CHARACTER(53) PRIMARY KEY, \ + Seq BIGINT UNSIGNED, \ + Comment TEXT \ );", "CREATE TABLE LocalAccounts ( \ ID CHARACTER(40) PRIMARY KEY, \ @@ -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 *); @@ -89,7 +88,7 @@ int HashNodeDBCount=sizeof(HashNodeDBInit)/sizeof(const char *); // Net node database holds nodes seen on the network const char *NetNodeDBInit[] = { - "CREATE TABLE KnownNodes ( \ + "CREATE TABLE KnownNodes ( \ Hanko CHARACTER(40) PRIMARY KEY, \ LastSeen TEXT, \ HaveContactInfo CHARACTER(1), \ @@ -98,3 +97,5 @@ const char *NetNodeDBInit[] = { int NetNodeDBCount=sizeof(NetNodeDBInit)/sizeof(const char *); + +// vim:ts=4 diff --git a/src/DeterministicKeys.cpp b/src/DeterministicKeys.cpp index 2222692770..43230afe1f 100644 --- a/src/DeterministicKeys.cpp +++ b/src/DeterministicKeys.cpp @@ -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,46 +109,48 @@ 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); return NULL; } - + if(!EC_KEY_set_public_key(pkey, pubPoint)) { EC_POINT_free(pubPoint); EC_KEY_free(pkey); return NULL; } - + 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 - BN_CTX* ctx=BN_CTX_new(); - if(ctx==NULL) return NULL; + EC_KEY* rootKey = CKey::GenerateRootPubKey(family.getFamilyGeneratorBN()); + const EC_POINT* rootPubKey = EC_KEY_get0_public_key(rootKey); + BN_CTX* ctx = BN_CTX_new(); + EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1); + EC_POINT* newPoint = 0; + BIGNUM* order = 0; + BIGNUM* hash = 0; + bool success = true; - EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1); - if(pkey==NULL) - { - BN_CTX_free(ctx); - return NULL; - } - EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED); + if (!ctx || !pkey) success = false; - 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) + EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED); + + if (success) { + newPoint = EC_POINT_new(EC_KEY_get0_group(pkey)); + if(!newPoint) success = false; } - BIGNUM* 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; + if (success) { + order = BN_new(); + + if(!order || !EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx)) + 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 - EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx); - BN_free(hash); - // 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); + if (success) { + // Calculate the corresponding public key. + EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx); - EC_POINT_free(newPoint); - BN_CTX_free(ctx); - return pkey; + // 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); + } + + 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; } - -EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, const BIGNUM* rootPrivKey, int seq) + +// --> 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; @@ -218,7 +229,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, const BIGNU return NULL; } EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED); - + BIGNUM* order=BN_new(); if(order==NULL) { @@ -226,7 +237,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, const BIGNU EC_KEY_free(pkey); return NULL; } - + if(!EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx)) { BN_free(order); @@ -271,5 +282,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, const BIGNU EC_POINT_free(pubKey); BN_CTX_free(ctx); - return pkey; + + return pkey; } +// vim:ts=4 diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 0a41ef5c27..a6d3bd57a1 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -15,13 +15,13 @@ #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) { mTransactionMap=boost::make_shared(); mAccountStateMap=boost::make_shared(); - + AccountState::pointer startAccount=boost::make_shared(masterID); startAccount->credit(startAmount); if(!addAccountState(startAccount)) @@ -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(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(state->getAccountID(), state->getRaw()); + SHAMapItem::pointer item=boost::make_shared(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(state->getAccountID(), state->getRaw()); + SHAMapItem::pointer item=boost::make_shared(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,12 +355,12 @@ 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(la1, 100000); - + ledger=Ledger::pointer(new Ledger(*ledger, 0)); // can't use make_shared AccountState::pointer as=ledger->getAccountState(la1); @@ -367,7 +368,7 @@ bool Ledger::unitTest() assert(as->getBalance()==100000); assert(as->getSeq()==0); as=ledger->getAccountState(la2); - assert(!as); + assert(!as); Transaction::pointer t=boost::make_shared(l1, l2->getAddress(), 2500, 0, 1); assert(!!t->getID()); @@ -377,7 +378,7 @@ bool Ledger::unitTest() std::cerr << "Transaction: " << tr << std::endl; #endif assert(tr==TR_SUCCESS); - +#endif return true; } diff --git a/src/Ledger.h b/src/Ledger.h index b1869875b3..255af429a9 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -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& 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); diff --git a/src/LedgerMaster.cpp b/src/LedgerMaster.cpp index d8958180bd..a37d96fe6f 100644 --- a/src/LedgerMaster.cpp +++ b/src/LedgerMaster.cpp @@ -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 diff --git a/src/LedgerMaster.h b/src/LedgerMaster.h index 4988fbf8fa..49fe36783a 100644 --- a/src/LedgerMaster.h +++ b/src/LedgerMaster.h @@ -37,7 +37,7 @@ public: Ledger::pointer getCurrentLedger() { return mCurrentLedger; } Ledger::pointer getClosingLedger() { return mFinalizingLedger; } - + void pushLedger(Ledger::pointer newLedger); Ledger::pointer getLedgerBySeq(uint32 index) @@ -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); diff --git a/src/LocalAccount.h b/src/LocalAccount.h index 4a8677d6a9..542ef2a500 100644 --- a/src/LocalAccount.h +++ b/src/LocalAccount.h @@ -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 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 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& 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); }; diff --git a/src/LocalTransaction.cpp b/src/LocalTransaction.cpp index beb1133cb9..f184228ba1 100644 --- a/src/LocalTransaction.cpp +++ b/src/LocalTransaction.cpp @@ -27,8 +27,7 @@ bool LocalTransaction::makeTransaction() Json::Value t=mTransaction->getJson(true); Json::StyledStreamWriter w; w.write(std::cerr, t); - -#endif +#endif return false; } return true; @@ -46,11 +45,16 @@ Json::Value LocalTransaction::getJson() const Json::Value ret(Json::objectValue); ret["Status"]="unfunded"; ret["Amount"]=boost::lexical_cast(mAmount); + Json::Value destination(Json::objectValue); - destination["AccountID"]=NewcoinAddress(mDestAcctID).GetString(); + destination["AccountID"]=mDestAcctID.humanAccountID(); + ret["Destination"]=destination; - return ret; + + return ret; } return mTransaction->getJson(true, isPaid(), isCredited()); } + +// vim:ts=4 diff --git a/src/LocalTransaction.h b/src/LocalTransaction.h index 2089aefa06..3913e12854 100644 --- a/src/LocalTransaction.h +++ b/src/LocalTransaction.h @@ -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; } diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 82949ae5d6..e5a1279c60 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -97,7 +97,7 @@ Transaction::pointer NetworkOPs::findTransactionByID(const uint256& transactionI } int NetworkOPs::findTransactionsBySource(std::list& 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& txns, } int NetworkOPs::findTransactionsByDestination(std::list& 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); } diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index aa8b168687..b7e94de71a 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -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&, const uint160& sourceAccount, + int findTransactionsBySource(std::list&, const NewcoinAddress& sourceAccount, uint32 minSeq, uint32 maxSeq); - int findTransactionsByDestination(std::list&, const uint160& destinationAccount, + int findTransactionsByDestination(std::list&, 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 diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index bb014da6e7..9666561227 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -1,58 +1,514 @@ #include "NewcoinAddress.h" +#include "key.h" #include "Config.h" #include "BitcoinUtil.h" +#include "openssl/ec.h" + #include - -bool NewcoinAddress::SetHash160(const uint160& hash160) -{ - SetData(51, &hash160, 20); - return true; -} - -bool NewcoinAddress::SetPubKey(const std::vector& vchPubKey) -{ - return SetHash160(Hash160(vchPubKey)); -} - -bool NewcoinAddress::IsValid() -{ - return nVersion == 51 && vchData.size() == 20; -} - NewcoinAddress::NewcoinAddress() { + version = VER_NONE; } -NewcoinAddress::NewcoinAddress(const uint160& hash160In) +bool NewcoinAddress::IsValid() { - SetHash160(hash160In); + return !vchData.empty(); } -NewcoinAddress::NewcoinAddress(const std::vector& vchPubKey) +// +// Hanko +// + +uint160 NewcoinAddress::getHanko() const { - SetPubKey(vchPubKey); + 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"); + } + + return 0; } -NewcoinAddress::NewcoinAddress(const std::string& strAddress) +std::string NewcoinAddress::humanHanko() const { - SetString(strAddress); -} + switch (version) { + case VER_NONE: + std::runtime_error("unset source"); + break; -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& 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& 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& 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& 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& 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& 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 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 diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index 9b1a299a19..7191b55e5c 100644 --- a/src/NewcoinAddress.h +++ b/src/NewcoinAddress.h @@ -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& vchPubKey); - NewcoinAddress(const std::string& strAddress); - NewcoinAddress(const char* pszAddress); - - bool SetHash160(const uint160& hash160); - bool SetPubKey(const std::vector& vchPubKey); bool IsValid(); - uint160 GetHash160() const; - std::string GetString() const; + + // + // Nodes + // + uint160 getHanko() const; + const std::vector& 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& vPublic); + + bool setNodePrivate(const std::string& strPrivate); + void setNodePrivate(uint256 hash256); + + // + // Accounts + // + uint160 getAccountID() const; + const std::vector& 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& 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& getFamilyGenerator() const; + + std::string humanFamilyGenerator() const; + + bool setFamilyGenerator(const std::string& strGenerator); + void setFamilyGenerator(const std::vector& 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 diff --git a/src/PubKeyCache.cpp b/src/PubKeyCache.cpp index ea3cede8ec..cc97bbbd8c 100644 --- a/src/PubKeyCache.cpp +++ b/src/PubKeyCache.cpp @@ -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::iterator it(mCache.find(id)); + std::map::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 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::iterator, bool> pit(mCache.insert(std::make_pair(id, key))); + std::pair::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 pk=key->GetPubKey(); diff --git a/src/PubKeyCache.h b/src/PubKeyCache.h index 9f5d37e50d..bf6995875c 100644 --- a/src/PubKeyCache.h +++ b/src/PubKeyCache.h @@ -5,20 +5,20 @@ #include -#include "uint256.h" +#include "NewcoinAddress.h" #include "key.h" class PubKeyCache { private: boost::mutex mLock; - std::map mCache; + std::map 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(); }; diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 615d1eb2eb..29e5399a61 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -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 - // createfamily + // createfamily FXXXX + // createfamily fXXXX // createfamily "" // createfamily std::string query; - uint160 family; - - uint256 privKey; + NewcoinAddress family; + NewcoinAddress seed; + 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 ¶ms) 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,24 +234,26 @@ Json::Value RPCServer::doAccountInfo(Json::Value ¶ms) as->addJson(ret); else { - NewcoinAddress ad(acctid); - ret[ad.GetString()]="NotFound"; + NewcoinAddress ad; + ad.setAccountID(acct); + ret[ad.humanAccountID()]="NotFound"; } return ret; } - + Json::Value RPCServer::doNewAccount(Json::Value ¶ms) { // newaccount [] std::string fParam; 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 ¶ms) { // lock // lock std::string fParam; + if(extractString(fParam, params, 0)) { // local - 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 ¶ms) -{ // unlock +{ // unlock FXXXX // unlock "" + 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 ¶ms) if(paramCount==0) { - std::vector familyIDs; + std::vector 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 ¶ms) 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 ¶ms) std::string keyNum; extractString(keyNum, params, 1); int kn=boost::lexical_cast(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; } } @@ -365,13 +387,13 @@ Json::Value RPCServer::doSendTo(Json::Value& params) int paramCount=getParamCount(params); if((paramCount<2)||(paramCount>3)) return JSONRPCError(500, "Invalid parameters"); - + std::string sDest, sAmount; 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 @@ -438,7 +460,7 @@ Json::Value RPCServer::doTx(Json::Value& params) if(!txn) return JSONRPCError(500, "Transaction not found"); return txn->getJson(true); } - + if(extractString(param2, params, 1)) { // family seq LocalAccount::pointer account=theApp->getWallet().parseAccount(param1+":"+param2); @@ -454,7 +476,7 @@ Json::Value RPCServer::doTx(Json::Value& params) // account } - return "not implemented"; + return "not implemented"; } Json::Value RPCServer::doLedger(Json::Value& params) @@ -476,6 +498,39 @@ Json::Value RPCServer::doLedger(Json::Value& params) return "not implemented"; } +Json::Value RPCServer::doAddUnl(Json::Value& params) { + // addUNL + // addUNL + 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 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 diff --git a/src/RPCServer.h b/src/RPCServer.h index ddeb970ef1..93f19ced90 100644 --- a/src/RPCServer.h +++ b/src/RPCServer.h @@ -7,14 +7,14 @@ #include "HttpRequest.h" #include "RequestParser.h" -#include "uint256.h" +#include "NewcoinAddress.h" class RPCServer : public boost::enable_shared_from_this { boost::asio::ip::tcp::socket mSocket; boost::array mReadBuffer; std::string mReplyStr; - + HttpRequest mIncomingRequest; HttpRequestParser mRequestParser; @@ -31,7 +31,7 @@ class RPCServer : public boost::enable_shared_from_this 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 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 pointer; diff --git a/src/Serializer.cpp b/src/Serializer.cpp index 6c083d7075..232c4060ea 100644 --- a/src/Serializer.cpp +++ b/src/Serializer.cpp @@ -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(); diff --git a/src/Serializer.h b/src/Serializer.h index 3f7efd5a1e..ce5a1174cc 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -19,7 +19,7 @@ class Serializer protected: std::vector mData; - + public: Serializer(int n=256) { mData.reserve(n); } Serializer(const std::vector &data) : mData(data) { ; } @@ -30,8 +30,9 @@ class Serializer int add16(uint16); int add32(uint32); // ledger indexes, account sequence int add64(uint64); // timestamps, amounts - int add160(const uint160&); // account names, hankos - int add256(const uint256&); // transaction and ledger hashes + 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 &vector); int addRaw(const void *ptr, int len); @@ -107,7 +108,7 @@ public: int getPos(void) { return mPos; } int getBytesLeft(); - + unsigned char get8() throw(); uint16 get16() throw(); uint32 get32() throw(); @@ -120,3 +121,4 @@ public: }; #endif +// vim:ts=4 diff --git a/src/Transaction.cpp b/src/Transaction.cpp index f58db8ca8f..01f27b37bb 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -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 &t, bool validate) : mStatus(INVALID) { + uint160 toAccountID; + uint160 fromAccountID; + Serializer s(t); if(s.getLength() &t, bool validate) : m std::vector pubKey; if(!s.getRaw(pubKey, BTxPSPubK, BTxLSPubK)) { assert(false); return; } + + mAccountTo.setAccountID(toAccountID); + mAccountFrom.setAccountID(fromAccountID); + mFromPubKey=boost::make_shared(); 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(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(mFromAccountSeq)); sql.append("','"); @@ -182,7 +192,7 @@ bool Transaction::save() const sql.append("','"); sql.append(boost::lexical_cast(mIdent)); sql.append("','"); - sql.append(mAccountTo.GetHex()); + sql.append(mAccountTo.humanAccountID()); sql.append("','"); sql.append(boost::lexical_cast(mAmount)); sql.append("','"); @@ -221,7 +231,7 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql) if(!db->executeSQL(sql.c_str(), true) || !db->startIterRows() || !db->getNextRow()) return Transaction::pointer(); - + db->getStr("TransID", transID); db->getStr("FromID", fromID); fromSeq=db->getBigInt("FromSeq"); @@ -238,14 +248,14 @@ 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(); - + TransStatus st(INVALID); switch(status[0]) { @@ -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(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) { diff --git a/src/Transaction.h b/src/Transaction.h index 1f0501b508..e3495c943d 100644 --- a/src/Transaction.h +++ b/src/Transaction.h @@ -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& 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& signature, uint32 inLedger, TransStatus status) : mTransactionID(transactionID), mAccountFrom(accountFrom), mAccountTo(accountTo), @@ -116,3 +116,4 @@ protected: }; #endif +// vim:ts=4 diff --git a/src/UniqueNodeList.cpp b/src/UniqueNodeList.cpp index 7e20294a45..503488bb3f 100644 --- a/src/UniqueNodeList.cpp +++ b/src/UniqueNodeList.cpp @@ -2,31 +2,40 @@ #include "Application.h" #include "Conversion.h" -void UniqueNodeList::addNode(uint160& hanko, std::vector& 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& 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(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(publicKey.c_str()), publicKey.size(), tmpStr); + sql.append(tmpStr); + sql.append(","); + db->escape(reinterpret_cast(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(); diff --git a/src/UniqueNodeList.h b/src/UniqueNodeList.h index 9727cb7c98..3341a0d2e0 100644 --- a/src/UniqueNodeList.h +++ b/src/UniqueNodeList.h @@ -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& 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 diff --git a/src/ValidationCollection.cpp b/src/ValidationCollection.cpp index c61a69d9ec..95d28d3030 100644 --- a/src/ValidationCollection.cpp +++ b/src/ValidationCollection.cpp @@ -1,6 +1,5 @@ #include "ValidationCollection.h" #include "Application.h" -#include "NewcoinAddress.h" #include "Config.h" #include "Conversion.h" #include "Application.h" diff --git a/src/Wallet.cpp b/src/Wallet.cpp index ae360c4f0e..fc86825258 100644 --- a/src/Wallet.cpp +++ b/src/Wallet.cpp @@ -21,38 +21,34 @@ #define CHECK_NEW_FAMILIES 500 #endif +// +// LocalAccount - an account +// + LocalAccount::LocalAccount(boost::shared_ptr 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(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::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(mFamily, mRootPubKey, seq); + return boost::make_shared(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(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,127 +134,62 @@ 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(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(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); - 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); + // sql.append("','"); + sql.append(boost::lexical_cast(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); - + sql.append(");"); ScopedLock sl(theApp->getWalletDB()->getDBLock()); 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(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(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::iterator it=mFamilies.begin(); - it!=mFamilies.end(); ++it) - { - if(it->second->getShortName()==shortName) - return it->first; - } - return 0; +NewcoinAddress Wallet::addFamily(const NewcoinAddress& familySeed, bool lock) +{ + 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(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(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& familyIDs) +void Wallet::getFamilies(std::vector& familyIDs) { boost::recursive_mutex::scoped_lock sl(mLock); familyIDs.reserve(mFamilies.size()); - for(std::map::iterator fit=mFamilies.begin(); fit!=mFamilies.end(); ++fit) + for(std::map::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::iterator fit=mFamilies.find(family); - if(fit==mFamilies.end()) return false; + + std::map::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::iterator fit=mFamilies.find(family); + std::map::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::iterator fit=mFamilies.find(family); + std::map::iterator fit=mFamilies.find(family); if(fit==mFamilies.end()) return Json::Value(Json::nullValue); assert(fit->second->getFamily()==family); return fit->second->getJson(); @@ -454,7 +348,7 @@ Json::Value Wallet::getFamilyJson(const uint160& family) void Wallet::load() { std::string sql("SELECT * FROM LocalAcctFamilies;"); - + ScopedLock sl(theApp->getWalletDB()->getDBLock()); Database *db=theApp->getWalletDB()->getDB(); if(!db->executeSQL(sql.c_str())) @@ -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); - LocalAccountFamily::pointer f(doPublic(rootpub, true, false)); + NewcoinAddress family; + + 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,67 +383,53 @@ 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::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::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::iterator fit=mFamilies.find(family); + std::map::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::iterator ait=mAccounts.find(acct); + + std::map::iterator ait=mAccounts.find(acct); if(ait!=mAccounts.end()) return ait->second; - + LocalAccount::pointer lac=boost::make_shared(fit->second, seq); mAccounts.insert(std::make_pair(acct, lac)); - + 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::iterator fit=mFamilies.find(family); + std::map::iterator fit=mFamilies.find(family); if(fit==mFamilies.end()) return LocalAccount::pointer(); - uint160 acct=fit->second->getAccount(seq, true); - - std::map::iterator ait=mAccounts.find(acct); + + NewcoinAddress acct=fit->second->getAccount(seq, true); + + std::map::iterator ait=mAccounts.find(acct); if(ait!=mAccounts.end()) return ait->second; - + LocalAccount::pointer lac=boost::make_shared(fit->second, seq); mAccounts.insert(std::make_pair(acct, lac)); 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::iterator ait=mAccounts.find(acctID); + std::map::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::iterator it=mAccounts.begin(); it!=mAccounts.end(); ++it) + for(std::map::iterator it=mAccounts.begin(); it!=mAccounts.end(); ++it) if(!it->second->isLocked() && (it->second->getEffectiveBalance()>=amount) ) return it->second; return LocalAccount::pointer(); @@ -566,62 +445,80 @@ LocalAccount::pointer Wallet::findAccountForTransaction(uint64 amount) LocalAccount::pointer Wallet::parseAccount(const std::string& specifier) { // : or - 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(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 + } + + return familyFound.IsValid() + ? getLocalAccount(familyFound, boost::lexical_cast(seq)) + : LocalAccount::pointer(); } -uint160 Wallet::peekKey(const uint160& family, int seq) +NewcoinAddress Wallet::peekKey(const NewcoinAddress& family, int seq) { boost::recursive_mutex::scoped_lock sl(mLock); - std::map::iterator fit=mFamilies.find(family); - if(fit==mFamilies.end()) return uint160(); + std::map::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::iterator fit=mFamilies.find(familyName); + std::map::iterator fit=mFamilies.find(familyName); if(fit==mFamilies.end()) return; std::map& acctMap=fit->second->getAcctMap(); for(std::map::iterator it=acctMap.begin(); it!=acctMap.end(); ++it) mAccounts.erase(it->second->getAddress()); - + 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::iterator fit=mFamilies.find(family); + std::map::iterator fit=mFamilies.find(family); if(fit!=mFamilies.end()) // already added { EC_KEY_free(pkey); @@ -657,33 +556,27 @@ 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(family, EC_KEY_get0_group(pkey), EC_KEY_get0_public_key(pkey)); + fam=boost::make_shared(family); mFamilies.insert(std::make_pair(family, fam)); if(do_db) fam->write(true); } sl.unlock(); - + EC_KEY_free(pkey); 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); + NewcoinAddress family; + family.setFamilyGenerator(familySeed); -// Extract family name - std::vector 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(); - boost::recursive_mutex::scoped_lock sl(mLock); LocalAccountFamily::pointer fam; - std::map::iterator it=mFamilies.find(family); + std::map::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(family, - EC_KEY_get0_group(base), EC_KEY_get0_public_key(base)); + fam=boost::make_shared(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::iterator fit=mFamilies.find(family); + std::map::iterator fit=mFamilies.find(family); if(fit==mFamilies.end()) return false; fit->second->lock(); return true; @@ -722,31 +613,33 @@ bool Wallet::lock(const uint160& family) void Wallet::lock() { boost::recursive_mutex::scoped_lock sl(mLock); - for(std::map::iterator fit=mFamilies.begin(); + for(std::map::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)); // privBase.SetHex("102031459e"); - + 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; #endif - + if(pub.addFamily(pubGen)!=fam) { assert(false); @@ -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; @@ -788,11 +681,12 @@ bool Wallet::unitTest() } } std::cerr << std::endl; - + pub.delFamily(fam); 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::iterator ait=mAccounts.begin(); ait!=mAccounts.end(); ++ait) + for(std::map::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::iterator lti=mTransactions.find(txn->getID()); if(lti!=mTransactions.end()) ltx=lti->second; - std::map::iterator lac=mAccounts.find(txn->getToAccount()); + std::map::iterator lac=mAccounts.find(txn->getToAccount()); if(lac!=mAccounts.end()) { // this is to a local account if(!ltx) @@ -840,10 +734,10 @@ void Wallet::applyTransaction(Transaction::pointer txn) lac->second->credit(txn->getAmount()-txn->getFee()); } } - + lac=mAccounts.find(txn->getFromAccount()); if(lac==mAccounts.end()) return; - + if ( (st!=INVALID) && (lac->second->getTxnSeq()==txn->getFromAccountSeq()) ) lac->second->incTxnSeq(); @@ -888,7 +782,7 @@ void Wallet::addLocalTransactions(Json::Value& ret) boost::recursive_mutex::scoped_lock sl(mLock); for(std::map::iterator it=mTransactions.begin(); it!=mTransactions.end(); ++it) - ret[it->first.GetHex()]=it->second->getJson(); + ret[it->first.GetHex()]=it->second->getJson(); } bool Wallet::getTxJson(const uint256& txn, Json::Value& ret) @@ -897,10 +791,11 @@ bool Wallet::getTxJson(const uint256& txn, Json::Value& ret) std::map::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::iterator it=mTransactions.begin(); @@ -908,7 +803,9 @@ bool Wallet::getTxsJson(const uint160& account, Json::Value& ret) { Transaction::pointer txn=it->second->getTransaction(); if(txn && ((account==txn->getFromAccount())||(account==txn->getToAccount())) ) - ret[it->first.GetHex()]=it->second->getJson(); + ret[it->first.GetHex()]=it->second->getJson(); } + return true; } +// vim:ts=4 diff --git a/src/Wallet.h b/src/Wallet.h index 112a88a2cd..4568428067 100644 --- a/src/Wallet.h +++ b/src/Wallet.h @@ -24,35 +24,32 @@ class Wallet protected: boost::recursive_mutex mLock; - std::map mFamilies; - std::map mAccounts; + std::map mFamilies; + std::map mAccounts; std::map 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& familyIDs); + void getFamilies(std::vector& 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); diff --git a/src/base58.h b/src/base58.h index bd99148b94..7f9ba24349 100644 --- a/src/base58.h +++ b/src/base58.h @@ -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 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 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 diff --git a/src/key.h b/src/key.h index d0728f151c..ba664caed7 100644 --- a/src/key.h +++ b/src/key.h @@ -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 diff --git a/src/uint256.h b/src/uint256.h index d4b75ea7ec..213b945b35 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -14,6 +14,8 @@ #include "types.h" +#include + #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++) @@ -292,7 +307,7 @@ public: return false; return true; } - + friend inline bool operator!=(const base_uint& a, const base_uint& b) { return (!(a == b)); @@ -415,22 +430,64 @@ public: } + friend class uint128; friend class uint160; friend class uint256; friend inline int Testuint256AdHoc(std::vector 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& vch) + { + if (vch.size() == sizeof(pn)) + memcpy(pn, &vch[0], sizeof(pn)); + else + memset(pn, 0, sizeof(pn)); + } + +}; ////////////////////////////////////////////////////////////////////////////// // @@ -490,7 +547,7 @@ public: else *this = 0; } - + base_uint256 to256() const; }; @@ -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 @@ -606,7 +658,7 @@ public: else *this = 0; } - + base_uint160 to160() const; }; @@ -792,3 +844,4 @@ inline int Testuint256AdHoc(std::vector vArg) } #endif +// vim:ts=4