mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Rework addresses.
This commit is contained in:
@@ -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')
|
||||
|
||||
@@ -8,19 +8,21 @@ AccountState::AccountState(const std::vector<unsigned char>& v)
|
||||
{
|
||||
Serializer s(v);
|
||||
mValid=false;
|
||||
if(!s.get160(mAccountID, 0)) { assert(false); return; }
|
||||
uint160 acct160 = mAccountID.getAccountID();
|
||||
|
||||
if(!s.get160(acct160, 0)) { assert(false); return; }
|
||||
if(!s.get64(mBalance, 20)) { assert(false); return; }
|
||||
if(!s.get32(mAccountSeq, 28)) { assert(false); return; }
|
||||
mValid=true;
|
||||
}
|
||||
|
||||
AccountState::AccountState(const uint160& id) : mAccountID(id), mBalance(0), mAccountSeq(0), mValid(true)
|
||||
AccountState::AccountState(const NewcoinAddress& id) : mAccountID(id), mBalance(0), mAccountSeq(0), mValid(true)
|
||||
{ ; }
|
||||
|
||||
std::vector<unsigned char> AccountState::getRaw() const
|
||||
{ // 20-byte acct ID, 8-byte balance, 4-byte sequence
|
||||
Serializer s(32);
|
||||
s.add160(mAccountID);
|
||||
s.add160(mAccountID.getAccountID());
|
||||
s.add64(mBalance);
|
||||
s.add32(mAccountSeq);
|
||||
return s.getData();
|
||||
@@ -45,10 +47,13 @@ bool AccountState::isHexAccountID(const std::string& acct)
|
||||
void AccountState::addJson(Json::Value& val)
|
||||
{
|
||||
Json::Value as(Json::objectValue);
|
||||
as["Account"]=mAccountID.GetHex();
|
||||
|
||||
// XXX Might want account public here, if available.
|
||||
as["Account"]=mAccountID.humanAccountID();
|
||||
as["Balance"]=boost::lexical_cast<std::string>(mBalance);
|
||||
as["SendSequence"]=mAccountSeq;
|
||||
if(!mValid) as["Invalid"]=true;
|
||||
NewcoinAddress nad(mAccountID);
|
||||
val[nad.GetString()]=as;
|
||||
|
||||
val[mAccountID.humanAccountID()]=as;
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "types.h"
|
||||
#include "uint256.h"
|
||||
#include "NewcoinAddress.h"
|
||||
|
||||
class AccountState
|
||||
{
|
||||
@@ -18,16 +19,16 @@ public:
|
||||
typedef boost::shared_ptr<AccountState> pointer;
|
||||
|
||||
private:
|
||||
uint160 mAccountID;
|
||||
NewcoinAddress mAccountID;
|
||||
uint64 mBalance;
|
||||
uint32 mAccountSeq;
|
||||
bool mValid;
|
||||
|
||||
public:
|
||||
AccountState(const uint160& mAccountID); // new account
|
||||
AccountState(const NewcoinAddress& mAccountID); // new account
|
||||
AccountState(const std::vector<unsigned char>&); // raw form
|
||||
|
||||
const uint160& getAccountID() const { return mAccountID; }
|
||||
const NewcoinAddress& getAccountID() const { return mAccountID; }
|
||||
uint64 getBalance() const { return mBalance; }
|
||||
uint32 getSeq() const { return mAccountSeq; }
|
||||
|
||||
@@ -57,3 +58,4 @@ public:
|
||||
};
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -49,10 +49,8 @@ int LedgerDBCount=sizeof(LedgerDBInit)/sizeof(const char *);
|
||||
// Wallet database holds local accounts and trusted nodes
|
||||
const char *WalletDBInit[] = {
|
||||
"CREATE TABLE LocalAcctFamilies ( \
|
||||
FamilyName CHARACTER(40) PRIMARY KEY, \
|
||||
RootPubKey CHARACTER(66), \
|
||||
FamilyGenerator CHARACTER(53) PRIMARY KEY, \
|
||||
Seq BIGINT UNSIGNED, \
|
||||
Name TEXT, \
|
||||
Comment TEXT \
|
||||
);",
|
||||
"CREATE TABLE LocalAccounts ( \
|
||||
@@ -62,15 +60,16 @@ const char *WalletDBInit[] = {
|
||||
Seq BIGINT UNSIGNED, \
|
||||
Balance BIGINT UNSIGNED, \
|
||||
LedgerSeq BIGINT UNSIGNED, \
|
||||
Name TEXT, \
|
||||
Comment TEXT \
|
||||
);",
|
||||
"CREATE TABLE TrustedNodes ( ` \
|
||||
"CREATE TABLE TrustedNodes ( \
|
||||
Hanko CHARACTER(40) PRIMARY KEY, \
|
||||
TrustLevel SMALLINT, \
|
||||
PubKey CHARACTER(66), \
|
||||
Comment TEXT \
|
||||
);" };
|
||||
|
||||
// TrustLevel SMALLINT,
|
||||
|
||||
int WalletDBCount=sizeof(WalletDBInit)/sizeof(const char *);
|
||||
|
||||
|
||||
@@ -98,3 +97,5 @@ const char *NetNodeDBInit[] = {
|
||||
|
||||
|
||||
int NetNodeDBCount=sizeof(NetNodeDBInit)/sizeof(const char *);
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -7,16 +7,23 @@
|
||||
|
||||
#include "Serializer.h"
|
||||
|
||||
uint256 CKey::PassPhraseToKey(const std::string& passPhrase)
|
||||
// <-- seed
|
||||
uint128 CKey::PassPhraseToKey(const std::string& passPhrase)
|
||||
{
|
||||
Serializer s;
|
||||
|
||||
s.addRaw(passPhrase.c_str(), passPhrase.size());
|
||||
uint256 ret(s.getSHA512Half());
|
||||
uint256 hash256 = s.getSHA512Half();
|
||||
uint128 ret(hash256);
|
||||
|
||||
s.secureErase();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EC_KEY* CKey::GenerateRootDeterministicKey(const uint256& key)
|
||||
// --> seed
|
||||
// <-- private root generator + public root generator
|
||||
EC_KEY* CKey::GenerateRootDeterministicKey(const uint128& seed)
|
||||
{
|
||||
BN_CTX* ctx=BN_CTX_new();
|
||||
if(!ctx) return NULL;
|
||||
@@ -49,8 +56,8 @@ EC_KEY* CKey::GenerateRootDeterministicKey(const uint256& key)
|
||||
int seq=0;
|
||||
do
|
||||
{ // private key must be non-zero and less than the curve's order
|
||||
Serializer s(72);
|
||||
s.add256(key);
|
||||
Serializer s((128+32)/8);
|
||||
s.add128(seed);
|
||||
s.add32(seq++);
|
||||
uint256 root=s.getSHA512Half();
|
||||
s.secureErase();
|
||||
@@ -102,22 +109,23 @@ EC_KEY* CKey::GenerateRootDeterministicKey(const uint256& key)
|
||||
return pkey;
|
||||
}
|
||||
|
||||
EC_KEY* CKey::GenerateRootPubKey(const std::string& pubHex)
|
||||
// Take newcoin address.
|
||||
// --> root public generator (consumes)
|
||||
// <-- root public generator in EC format
|
||||
EC_KEY* CKey::GenerateRootPubKey(BIGNUM* pubGenerator)
|
||||
{
|
||||
BIGNUM* bn=NULL;
|
||||
BN_hex2bn(&bn, pubHex.c_str());
|
||||
if(bn==NULL) return NULL;
|
||||
if(pubGenerator==NULL) return NULL;
|
||||
|
||||
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if(!pkey)
|
||||
{
|
||||
BN_free(bn);
|
||||
BN_free(pubGenerator);
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
EC_POINT* pubPoint=EC_POINT_bn2point(EC_KEY_get0_group(pkey), bn, NULL, NULL);
|
||||
BN_free(bn);
|
||||
EC_POINT* pubPoint=EC_POINT_bn2point(EC_KEY_get0_group(pkey), pubGenerator, NULL, NULL);
|
||||
BN_free(pubGenerator);
|
||||
if(!pubPoint)
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
@@ -134,14 +142,15 @@ EC_KEY* CKey::GenerateRootPubKey(const std::string& pubHex)
|
||||
return pkey;
|
||||
}
|
||||
|
||||
static BIGNUM* makeHash(const uint160& family, int seq, BIGNUM* order)
|
||||
// --> public generator
|
||||
static BIGNUM* makeHash(const NewcoinAddress& family, int seq, BIGNUM* order)
|
||||
{
|
||||
int subSeq=0;
|
||||
BIGNUM* ret=NULL;
|
||||
do
|
||||
{
|
||||
Serializer s(28);
|
||||
s.add160(family);
|
||||
Serializer s((128+32+32)/8);
|
||||
s.add128(family.getFamilySeed());
|
||||
s.add32(seq);
|
||||
s.add32(subSeq++);
|
||||
uint256 root=s.getSHA512Half();
|
||||
@@ -149,64 +158,66 @@ static BIGNUM* makeHash(const uint160& family, int seq, BIGNUM* order)
|
||||
ret=BN_bin2bn((const unsigned char *) &root, sizeof(root), ret);
|
||||
if(!ret) return NULL;
|
||||
} while (BN_is_zero(ret) || (BN_cmp(ret, order)>=0));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EC_KEY* CKey::GeneratePublicDeterministicKey(const uint160& family, const EC_POINT* rootPubKey, int seq)
|
||||
// --> public generator
|
||||
EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& family, int seq)
|
||||
{ // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
|
||||
EC_KEY* rootKey = CKey::GenerateRootPubKey(family.getFamilyGeneratorBN());
|
||||
const EC_POINT* rootPubKey = EC_KEY_get0_public_key(rootKey);
|
||||
BN_CTX* ctx = BN_CTX_new();
|
||||
if(ctx==NULL) return NULL;
|
||||
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if(pkey==NULL)
|
||||
{
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
EC_POINT* newPoint = 0;
|
||||
BIGNUM* order = 0;
|
||||
BIGNUM* hash = 0;
|
||||
bool success = true;
|
||||
|
||||
if (!ctx || !pkey) success = false;
|
||||
|
||||
if (success)
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
EC_POINT *newPoint=EC_POINT_new(EC_KEY_get0_group(pkey));
|
||||
if(newPoint==NULL)
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
if (success) {
|
||||
newPoint = EC_POINT_new(EC_KEY_get0_group(pkey));
|
||||
if(!newPoint) success = false;
|
||||
}
|
||||
|
||||
BIGNUM* order=BN_new();
|
||||
if (success) {
|
||||
order = BN_new();
|
||||
|
||||
if(!order || !EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
|
||||
{
|
||||
if(order) BN_free(order);
|
||||
EC_KEY_free(pkey);
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
success = false;
|
||||
}
|
||||
|
||||
// calculate the private additional key
|
||||
BIGNUM* hash=makeHash(family, seq, order);
|
||||
BN_free(order);
|
||||
if(hash==NULL)
|
||||
{
|
||||
EC_POINT_free(newPoint);
|
||||
BN_CTX_free(ctx);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
// Calculate the private additional key.
|
||||
if (success) {
|
||||
hash = makeHash(family, seq, order);
|
||||
if(!hash) success = false;
|
||||
}
|
||||
|
||||
// calculate the corresponding public key
|
||||
if (success) {
|
||||
// Calculate the corresponding public key.
|
||||
EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx);
|
||||
BN_free(hash);
|
||||
|
||||
// add the master public key and set
|
||||
// Add the master public key and set.
|
||||
EC_POINT_add(EC_KEY_get0_group(pkey), newPoint, newPoint, rootPubKey, ctx);
|
||||
EC_KEY_set_public_key(pkey, newPoint);
|
||||
|
||||
EC_POINT_free(newPoint);
|
||||
BN_CTX_free(ctx);
|
||||
return pkey;
|
||||
}
|
||||
|
||||
EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, const BIGNUM* rootPrivKey, int seq)
|
||||
if (order) BN_free(order);
|
||||
if (hash) BN_free(hash);
|
||||
if (newPoint) EC_POINT_free(newPoint);
|
||||
if (ctx) BN_CTX_free(ctx);
|
||||
if (rootKey) EC_KEY_free(rootKey);
|
||||
if (pkey && !success) EC_KEY_free(pkey);
|
||||
|
||||
return success ? pkey : NULL;
|
||||
}
|
||||
|
||||
// --> root private key
|
||||
EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& family, const BIGNUM* rootPrivKey, int seq)
|
||||
{ // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
|
||||
BN_CTX* ctx=BN_CTX_new();
|
||||
if(ctx==NULL) return NULL;
|
||||
@@ -271,5 +282,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, const BIGNU
|
||||
|
||||
EC_POINT_free(pubKey);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return pkey;
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "Wallet.h"
|
||||
#include "BinaryFormats.h"
|
||||
|
||||
Ledger::Ledger(const uint160& masterID, uint64 startAmount) :
|
||||
Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) :
|
||||
mFeeHeld(0), mTimeStamp(0), mLedgerSeq(0),
|
||||
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false)
|
||||
{
|
||||
@@ -110,13 +110,13 @@ void Ledger::addRaw(Serializer &s)
|
||||
s.add64(mTimeStamp);
|
||||
}
|
||||
|
||||
AccountState::pointer Ledger::getAccountState(const uint160& accountID)
|
||||
AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Ledger:getAccountState(" << accountID.GetHex() << ")" << std::endl;
|
||||
std::cerr << "Ledger:getAccountState(" << accountID.humanAccountID() << ")" << std::endl;
|
||||
#endif
|
||||
ScopedLock l(mTransactionMap->Lock());
|
||||
SHAMapItem::pointer item=mAccountStateMap->peekItem(accountID.to256());
|
||||
SHAMapItem::pointer item=mAccountStateMap->peekItem(accountID.getAccountID().to256());
|
||||
if(!item)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -127,10 +127,10 @@ AccountState::pointer Ledger::getAccountState(const uint160& accountID)
|
||||
return boost::make_shared<AccountState>(item->getData());
|
||||
}
|
||||
|
||||
uint64 Ledger::getBalance(const uint160& accountID) const
|
||||
uint64 Ledger::getBalance(const NewcoinAddress& accountID) const
|
||||
{
|
||||
ScopedLock l(mTransactionMap->Lock());
|
||||
SHAMapItem::pointer item=mAccountStateMap->peekItem(accountID.to256());
|
||||
SHAMapItem::pointer item=mAccountStateMap->peekItem(accountID.getAccountID().to256());
|
||||
if(!item) return 0;
|
||||
return AccountState(item->getData()).getBalance();
|
||||
}
|
||||
@@ -138,7 +138,7 @@ uint64 Ledger::getBalance(const uint160& accountID) const
|
||||
bool Ledger::updateAccountState(AccountState::pointer state)
|
||||
{
|
||||
assert(!mAccepted);
|
||||
SHAMapItem::pointer item=boost::make_shared<SHAMapItem>(state->getAccountID(), state->getRaw());
|
||||
SHAMapItem::pointer item=boost::make_shared<SHAMapItem>(state->getAccountID().getAccountID(), state->getRaw());
|
||||
return mAccountStateMap->updateGiveItem(item, false);
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ bool Ledger::addAccountState(AccountState::pointer state)
|
||||
{
|
||||
assert(!mAccepted);
|
||||
assert( (state->getBalance()==0) || (state->getSeq()>0) );
|
||||
SHAMapItem::pointer item=boost::make_shared<SHAMapItem>(state->getAccountID(), state->getRaw());
|
||||
SHAMapItem::pointer item=boost::make_shared<SHAMapItem>(state->getAccountID().getAccountID(), state->getRaw());
|
||||
return mAccountStateMap->addGiveItem(item, false);
|
||||
}
|
||||
|
||||
@@ -345,6 +345,7 @@ void LocalAccount::syncLedger()
|
||||
|
||||
bool Ledger::unitTest()
|
||||
{
|
||||
#if 0
|
||||
uint160 la1=theApp->getWallet().addFamily(CKey::PassPhraseToKey("This is my payphrase!"), false);
|
||||
uint160 la2=theApp->getWallet().addFamily(CKey::PassPhraseToKey("Another payphrase"), false);
|
||||
|
||||
@@ -354,8 +355,8 @@ bool Ledger::unitTest()
|
||||
assert(l1->getAddress()==la1);
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Account1: " << la1.GetHex() << std::endl;
|
||||
std::cerr << "Account2: " << la2.GetHex() << std::endl;
|
||||
std::cerr << "Account1: " << la1.humanAccountID() << std::endl;
|
||||
std::cerr << "Account2: " << la2.humanAccountID() << std::endl;
|
||||
#endif
|
||||
|
||||
Ledger::pointer ledger=boost::make_shared<Ledger>(la1, 100000);
|
||||
@@ -377,7 +378,7 @@ bool Ledger::unitTest()
|
||||
std::cerr << "Transaction: " << tr << std::endl;
|
||||
#endif
|
||||
assert(tr==TR_SUCCESS);
|
||||
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ protected:
|
||||
static Ledger::pointer getSQL(const std::string& sqlStatement);
|
||||
|
||||
public:
|
||||
Ledger(const uint160& masterID, uint64 startAmount); // used for the starting bootstrap ledger
|
||||
Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger
|
||||
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||
uint64 feeHeld, uint64 timeStamp, uint32 ledgerSeq); // used for received ledgers
|
||||
Ledger(const std::vector<unsigned char>& rawLedger);
|
||||
@@ -97,9 +97,9 @@ public:
|
||||
|
||||
// mid level functions
|
||||
bool hasTransaction(const uint256& TransID) const;
|
||||
AccountState::pointer getAccountState(const uint160& acctID);
|
||||
AccountState::pointer getAccountState(const NewcoinAddress& acctID);
|
||||
Transaction::pointer getTransaction(const uint256& transID) const;
|
||||
uint64 getBalance(const uint160& acctID) const;
|
||||
uint64 getBalance(const NewcoinAddress& acctID) const;
|
||||
|
||||
// high level functions
|
||||
TransResult applyTransaction(Transaction::pointer trans);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -14,8 +14,8 @@ public:
|
||||
protected:
|
||||
// core account information
|
||||
CKey::pointer mPublicKey;
|
||||
uint160 mAcctID;
|
||||
std::string mName, mComment;
|
||||
NewcoinAddress mAcctID;
|
||||
std::string mComment;
|
||||
|
||||
// family information
|
||||
boost::shared_ptr<LocalAccountFamily> mFamily;
|
||||
@@ -35,13 +35,10 @@ public:
|
||||
bool updateName(); // writes changed name/comment
|
||||
bool updateBalance(); // writes changed balance/seq
|
||||
|
||||
const uint160& getAddress() const { return mAcctID; }
|
||||
const NewcoinAddress& getAddress() const { return mAcctID; }
|
||||
int getAcctFSeq() const { return mAccountFSeq; }
|
||||
|
||||
std::string getLocalAccountName() const; // The name used locally to identify this account
|
||||
std::string getAccountName() const; // The normal account name used to send to this account
|
||||
std::string getFullName() const;
|
||||
std::string getShortName() const;
|
||||
std::string getFamilyName() const;
|
||||
|
||||
bool isLocked() const;
|
||||
@@ -71,44 +68,40 @@ public:
|
||||
protected:
|
||||
std::map<int, LocalAccount::pointer> mAccounts;
|
||||
|
||||
uint160 mFamily; // the name for this account family
|
||||
EC_POINT* mRootPubKey;
|
||||
NewcoinAddress mFamily; // Family generator
|
||||
|
||||
uint32 mLastSeq;
|
||||
std::string mName, mComment;
|
||||
std::string mComment;
|
||||
|
||||
BIGNUM* mRootPrivateKey;
|
||||
|
||||
public:
|
||||
|
||||
LocalAccountFamily(const uint160& family, const EC_GROUP* group, const EC_POINT* pubKey);
|
||||
LocalAccountFamily(const NewcoinAddress& family);
|
||||
~LocalAccountFamily();
|
||||
|
||||
const uint160& getFamily() const { return mFamily; }
|
||||
const NewcoinAddress& getFamily() const { return mFamily; }
|
||||
|
||||
void unlock(const BIGNUM* privateKey);
|
||||
void unlock(BIGNUM* privateKey);
|
||||
void lock();
|
||||
bool isLocked() const { return mRootPrivateKey==NULL; }
|
||||
|
||||
void setSeq(uint32 s) { mLastSeq=s; }
|
||||
uint32 getSeq() { return mLastSeq; }
|
||||
void setName(const std::string& n) { mName=n; }
|
||||
void setComment(const std::string& c) { mComment=c; }
|
||||
|
||||
std::map<int, LocalAccount::pointer>& getAcctMap() { return mAccounts; }
|
||||
LocalAccount::pointer get(int seq);
|
||||
uint160 getAccount(int seq, bool keep);
|
||||
NewcoinAddress getAccount(int seq, bool keep);
|
||||
CKey::pointer getPrivateKey(int seq);
|
||||
CKey::pointer getPublicKey(int seq);
|
||||
|
||||
std::string getPubGenHex() const; // The text name of the public key
|
||||
std::string getShortName() const { return mName; }
|
||||
std::string getComment() const { return mComment; }
|
||||
Json::Value getJson() const;
|
||||
|
||||
static std::string getSQLFields();
|
||||
std::string getSQL() const;
|
||||
static LocalAccountFamily::pointer readFamily(const uint160& family);
|
||||
static LocalAccountFamily::pointer readFamily(const NewcoinAddress& family);
|
||||
void write(bool is_new);
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ bool LocalTransaction::makeTransaction()
|
||||
Json::Value t=mTransaction->getJson(true);
|
||||
Json::StyledStreamWriter w;
|
||||
w.write(std::cerr, t);
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -46,11 +45,16 @@ Json::Value LocalTransaction::getJson() const
|
||||
Json::Value ret(Json::objectValue);
|
||||
ret["Status"]="unfunded";
|
||||
ret["Amount"]=boost::lexical_cast<std::string>(mAmount);
|
||||
|
||||
Json::Value destination(Json::objectValue);
|
||||
destination["AccountID"]=NewcoinAddress(mDestAcctID).GetString();
|
||||
destination["AccountID"]=mDestAcctID.humanAccountID();
|
||||
|
||||
ret["Destination"]=destination;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return mTransaction->getJson(true, isPaid(), isCredited());
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -97,7 +97,7 @@ Transaction::pointer NetworkOPs::findTransactionByID(const uint256& transactionI
|
||||
}
|
||||
|
||||
int NetworkOPs::findTransactionsBySource(std::list<Transaction::pointer>& txns,
|
||||
const uint160& sourceAccount, uint32 minSeq, uint32 maxSeq)
|
||||
const NewcoinAddress& sourceAccount, uint32 minSeq, uint32 maxSeq)
|
||||
{
|
||||
AccountState::pointer state=getAccountState(sourceAccount);
|
||||
if(!state) return 0;
|
||||
@@ -119,13 +119,13 @@ int NetworkOPs::findTransactionsBySource(std::list<Transaction::pointer>& txns,
|
||||
}
|
||||
|
||||
int NetworkOPs::findTransactionsByDestination(std::list<Transaction::pointer>& txns,
|
||||
const uint160& destinationAccount, uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions)
|
||||
const NewcoinAddress& destinationAccount, uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions)
|
||||
{
|
||||
// WRITEME
|
||||
return 0;
|
||||
}
|
||||
|
||||
AccountState::pointer NetworkOPs::getAccountState(const uint160& accountID)
|
||||
AccountState::pointer NetworkOPs::getAccountState(const NewcoinAddress& accountID)
|
||||
{
|
||||
return theApp->getMasterLedger().getCurrentLedger()->getAccountState(accountID);
|
||||
}
|
||||
|
||||
@@ -36,13 +36,13 @@ public:
|
||||
// transaction operations
|
||||
Transaction::pointer processTransaction(Transaction::pointer transaction, Peer* source=NULL);
|
||||
Transaction::pointer findTransactionByID(const uint256& transactionID);
|
||||
int findTransactionsBySource(std::list<Transaction::pointer>&, const uint160& sourceAccount,
|
||||
int findTransactionsBySource(std::list<Transaction::pointer>&, const NewcoinAddress& sourceAccount,
|
||||
uint32 minSeq, uint32 maxSeq);
|
||||
int findTransactionsByDestination(std::list<Transaction::pointer>&, const uint160& destinationAccount,
|
||||
int findTransactionsByDestination(std::list<Transaction::pointer>&, const NewcoinAddress& destinationAccount,
|
||||
uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions);
|
||||
|
||||
// account operations
|
||||
AccountState::pointer getAccountState(const uint160& accountID);
|
||||
AccountState::pointer getAccountState(const NewcoinAddress& accountID);
|
||||
|
||||
// contact block operations
|
||||
|
||||
|
||||
@@ -1,58 +1,514 @@
|
||||
#include "NewcoinAddress.h"
|
||||
#include "key.h"
|
||||
#include "Config.h"
|
||||
#include "BitcoinUtil.h"
|
||||
#include "openssl/ec.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
||||
bool NewcoinAddress::SetHash160(const uint160& hash160)
|
||||
NewcoinAddress::NewcoinAddress()
|
||||
{
|
||||
SetData(51, &hash160, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::SetPubKey(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
return SetHash160(Hash160(vchPubKey));
|
||||
version = VER_NONE;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::IsValid()
|
||||
{
|
||||
return nVersion == 51 && vchData.size() == 20;
|
||||
return !vchData.empty();
|
||||
}
|
||||
|
||||
NewcoinAddress::NewcoinAddress()
|
||||
//
|
||||
// Hanko
|
||||
//
|
||||
|
||||
uint160 NewcoinAddress::getHanko() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_HANKO:
|
||||
return uint160(vchData);
|
||||
|
||||
case VER_NODE_PUBLIC:
|
||||
// Note, we are encoding the left or right.
|
||||
return Hash160(vchData);
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
NewcoinAddress::NewcoinAddress(const uint160& hash160In)
|
||||
{
|
||||
SetHash160(hash160In);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NewcoinAddress::NewcoinAddress(const std::vector<unsigned char>& vchPubKey)
|
||||
std::string NewcoinAddress::humanHanko() const
|
||||
{
|
||||
SetPubKey(vchPubKey);
|
||||
}
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
NewcoinAddress::NewcoinAddress(const std::string& strAddress)
|
||||
{
|
||||
SetString(strAddress);
|
||||
}
|
||||
|
||||
NewcoinAddress::NewcoinAddress(const char* pszAddress)
|
||||
{
|
||||
SetString(pszAddress);
|
||||
}
|
||||
|
||||
uint160 NewcoinAddress::GetHash160() const
|
||||
{
|
||||
assert(vchData.size() == 20);
|
||||
uint160 hash160;
|
||||
memcpy(&hash160, &vchData[0], 20);
|
||||
return hash160;
|
||||
}
|
||||
|
||||
std::string NewcoinAddress::GetString() const
|
||||
{
|
||||
case VER_HANKO:
|
||||
return ToString();
|
||||
|
||||
case VER_NODE_PUBLIC:
|
||||
{
|
||||
NewcoinAddress hanko;
|
||||
|
||||
(void) hanko.setHanko(getHanko());
|
||||
|
||||
return hanko.ToString();
|
||||
}
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::setHanko(const std::string& strHanko)
|
||||
{
|
||||
return SetString(strHanko.c_str(), VER_HANKO);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setHanko(const uint160& hash160)
|
||||
{
|
||||
SetData(VER_HANKO, hash160.begin(), 20);
|
||||
}
|
||||
|
||||
//
|
||||
// NodePublic
|
||||
//
|
||||
|
||||
const std::vector<unsigned char>& NewcoinAddress::getNodePublic() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_HANKO:
|
||||
std::runtime_error("public not available from hanko");
|
||||
break;
|
||||
|
||||
case VER_NODE_PUBLIC:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return vchData;
|
||||
}
|
||||
|
||||
std::string NewcoinAddress::humanNodePublic() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_HANKO:
|
||||
std::runtime_error("public not available from hanko");
|
||||
break;
|
||||
|
||||
case VER_NODE_PUBLIC:
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::setNodePublic(const std::string& strPublic)
|
||||
{
|
||||
return SetString(strPublic.c_str(), VER_NODE_PUBLIC);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setNodePublic(const std::vector<unsigned char>& vPublic)
|
||||
{
|
||||
SetData(VER_NODE_PUBLIC, vPublic);
|
||||
}
|
||||
|
||||
//
|
||||
// NodePrivate
|
||||
//
|
||||
|
||||
uint256 NewcoinAddress::getNodePrivate() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_NODE_PRIVATE:
|
||||
// Nothing
|
||||
break;
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return uint256(vchData);
|
||||
}
|
||||
|
||||
std::string NewcoinAddress::humanNodePrivate() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_NODE_PRIVATE:
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::setNodePrivate(const std::string& strPrivate)
|
||||
{
|
||||
return SetString(strPrivate.c_str(), VER_NODE_PRIVATE);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setNodePrivate(uint256 hash256)
|
||||
{
|
||||
SetData(VER_NODE_PRIVATE, hash256.begin(), 32);
|
||||
}
|
||||
|
||||
//
|
||||
// AccountID
|
||||
//
|
||||
|
||||
uint160 NewcoinAddress::getAccountID() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_ACCOUNT_ID:
|
||||
return uint160(vchData);
|
||||
|
||||
case VER_ACCOUNT_PUBLIC:
|
||||
// Note, we are encoding the left or right.
|
||||
return Hash160(vchData);
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string NewcoinAddress::humanAccountID() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_ACCOUNT_ID:
|
||||
return ToString();
|
||||
|
||||
case VER_ACCOUNT_PUBLIC:
|
||||
{
|
||||
NewcoinAddress accountID;
|
||||
|
||||
(void) accountID.setHanko(getAccountID());
|
||||
|
||||
return accountID.ToString();
|
||||
}
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::setAccountID(const std::string& strAccountID)
|
||||
{
|
||||
return SetString(strAccountID.c_str(), VER_ACCOUNT_ID);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setAccountID(const uint160& hash160)
|
||||
{
|
||||
SetData(VER_ACCOUNT_ID, hash160.begin(), 20);
|
||||
}
|
||||
|
||||
//
|
||||
// AccountPublic
|
||||
//
|
||||
|
||||
const std::vector<unsigned char>& NewcoinAddress::getAccountPublic() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_ACCOUNT_ID:
|
||||
std::runtime_error("public not available from account id");
|
||||
break;
|
||||
|
||||
case VER_ACCOUNT_PUBLIC:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return vchData;
|
||||
}
|
||||
|
||||
std::string NewcoinAddress::humanAccountPublic() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_ACCOUNT_ID:
|
||||
std::runtime_error("public not available from account id");
|
||||
break;
|
||||
|
||||
case VER_ACCOUNT_PUBLIC:
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::setAccountPublic(const std::string& strPublic)
|
||||
{
|
||||
return SetString(strPublic.c_str(), VER_ACCOUNT_PUBLIC);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setAccountPublic(const std::vector<unsigned char>& vPublic)
|
||||
{
|
||||
SetData(VER_ACCOUNT_PUBLIC, vPublic);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setAccountPublic(const NewcoinAddress& generator, int seq)
|
||||
{
|
||||
CKey pubkey = CKey(generator, seq);
|
||||
|
||||
setAccountPublic(pubkey.GetPubKey());
|
||||
}
|
||||
|
||||
//
|
||||
// AccountPrivate
|
||||
//
|
||||
|
||||
uint256 NewcoinAddress::getAccountPrivate() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_ACCOUNT_PRIVATE:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return uint256(vchData);
|
||||
}
|
||||
|
||||
std::string NewcoinAddress::humanAccountPrivate() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_ACCOUNT_PRIVATE:
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::setAccountPrivate(const std::string& strPrivate)
|
||||
{
|
||||
return SetString(strPrivate.c_str(), VER_ACCOUNT_PRIVATE);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setAccountPrivate(uint256 hash256)
|
||||
{
|
||||
SetData(VER_ACCOUNT_PRIVATE, hash256.begin(), 32);
|
||||
}
|
||||
|
||||
//
|
||||
// Family Generators
|
||||
//
|
||||
|
||||
BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_FAMILY_GENERATOR:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
// Convert to big-endian
|
||||
unsigned char be[vchData.size()];
|
||||
|
||||
std::reverse_copy(vchData.begin(), vchData.end(), &be[0]);
|
||||
|
||||
return BN_bin2bn(be, vchData.size(), NULL);
|
||||
}
|
||||
|
||||
const std::vector<unsigned char>& NewcoinAddress::getFamilyGenerator() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_FAMILY_GENERATOR:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return vchData;
|
||||
}
|
||||
|
||||
std::string NewcoinAddress::humanFamilyGenerator() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_FAMILY_GENERATOR:
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// YYY Would be nice if you could pass a family seed and derive the generator.
|
||||
bool NewcoinAddress::setFamilyGenerator(const std::string& strGenerator)
|
||||
{
|
||||
return SetString(strGenerator.c_str(), VER_FAMILY_GENERATOR);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setFamilyGenerator(const std::vector<unsigned char>& vPublic)
|
||||
{
|
||||
SetData(VER_FAMILY_GENERATOR, vPublic);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setFamilyGenerator(const NewcoinAddress& seed)
|
||||
{
|
||||
seed.seedInfo(this, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Family Seed
|
||||
//
|
||||
|
||||
void NewcoinAddress::seedInfo(NewcoinAddress* dstGenerator, BIGNUM** dstPrivateKey) const
|
||||
{
|
||||
// Generate root key
|
||||
EC_KEY *base=CKey::GenerateRootDeterministicKey(getFamilySeed());
|
||||
|
||||
// Extract family name
|
||||
std::vector<unsigned char> rootPubKey(33, 0);
|
||||
unsigned char *begin=&rootPubKey[0];
|
||||
i2o_ECPublicKey(base, &begin);
|
||||
while(rootPubKey.size()<33) rootPubKey.push_back((unsigned char)0);
|
||||
|
||||
if (dstGenerator)
|
||||
dstGenerator->setFamilyGenerator(rootPubKey);
|
||||
|
||||
if (dstPrivateKey)
|
||||
*dstPrivateKey = BN_dup(EC_KEY_get0_private_key(base));
|
||||
|
||||
EC_KEY_free(base);
|
||||
}
|
||||
|
||||
uint128 NewcoinAddress::getFamilySeed() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_FAMILY_SEED:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return uint128(vchData);
|
||||
}
|
||||
|
||||
BIGNUM* NewcoinAddress::getFamilyPrivateKey() const
|
||||
{
|
||||
BIGNUM* ret;
|
||||
|
||||
seedInfo(0, &ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string NewcoinAddress::humanFamilySeed() const
|
||||
{
|
||||
switch (version) {
|
||||
case VER_NONE:
|
||||
std::runtime_error("unset source");
|
||||
break;
|
||||
|
||||
case VER_FAMILY_SEED:
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
std::runtime_error("bad source");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::setFamilySeed(const std::string& strSeed)
|
||||
{
|
||||
return SetString(strSeed.c_str(), VER_FAMILY_SEED);
|
||||
}
|
||||
|
||||
void NewcoinAddress::setFamilySeed(uint128 hash128) {
|
||||
SetData(VER_FAMILY_SEED, hash128.begin(), 16);
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
@@ -2,26 +2,96 @@
|
||||
#define __NEWCOIN_ADDRESS__
|
||||
|
||||
#include "base58.h"
|
||||
#include "uint256.h"
|
||||
|
||||
|
||||
// TODO: https://en.bitcoin.it/wiki/Address
|
||||
// TODO: Why do we need steps 5 and 6? why not just use a checksum function to get the checksum?
|
||||
|
||||
//
|
||||
// Used to hold addresses and parse and produce human formats.
|
||||
//
|
||||
class NewcoinAddress : public CBase58Data
|
||||
{
|
||||
private:
|
||||
typedef enum {
|
||||
VER_NONE = 1,
|
||||
VER_HANKO = 13,
|
||||
VER_NODE_PUBLIC = 18,
|
||||
VER_NODE_PRIVATE = 23,
|
||||
VER_ACCOUNT_ID = 0,
|
||||
VER_ACCOUNT_PUBLIC = 3,
|
||||
VER_ACCOUNT_PRIVATE = 8,
|
||||
VER_FAMILY_GENERATOR = 28,
|
||||
VER_FAMILY_SEED = 33,
|
||||
} VersionEncoding;
|
||||
|
||||
VersionEncoding version;
|
||||
|
||||
void seedInfo(NewcoinAddress* dstGenerator, BIGNUM** dstPrivateKey) const;
|
||||
|
||||
public:
|
||||
NewcoinAddress();
|
||||
NewcoinAddress(const uint160& hash160In);
|
||||
NewcoinAddress(const std::vector<unsigned char>& vchPubKey);
|
||||
NewcoinAddress(const std::string& strAddress);
|
||||
NewcoinAddress(const char* pszAddress);
|
||||
|
||||
bool SetHash160(const uint160& hash160);
|
||||
bool SetPubKey(const std::vector<unsigned char>& vchPubKey);
|
||||
|
||||
bool IsValid();
|
||||
uint160 GetHash160() const;
|
||||
std::string GetString() const;
|
||||
|
||||
//
|
||||
// Nodes
|
||||
//
|
||||
uint160 getHanko() const;
|
||||
const std::vector<unsigned char>& getNodePublic() const;
|
||||
uint256 getNodePrivate() const;
|
||||
|
||||
std::string humanHanko() const;
|
||||
std::string humanNodePublic() const;
|
||||
std::string humanNodePrivate() const;
|
||||
|
||||
bool setHanko(const std::string& strHanko);
|
||||
void setHanko(const uint160& hash160);
|
||||
|
||||
bool setNodePublic(const std::string& strPublic);
|
||||
void setNodePublic(const std::vector<unsigned char>& vPublic);
|
||||
|
||||
bool setNodePrivate(const std::string& strPrivate);
|
||||
void setNodePrivate(uint256 hash256);
|
||||
|
||||
//
|
||||
// Accounts
|
||||
//
|
||||
uint160 getAccountID() const;
|
||||
const std::vector<unsigned char>& getAccountPublic() const;
|
||||
uint256 getAccountPrivate() const;
|
||||
|
||||
std::string humanAccountID() const;
|
||||
std::string humanAccountPublic() const;
|
||||
std::string humanAccountPrivate() const;
|
||||
|
||||
bool setAccountID(const std::string& strAccountID);
|
||||
void setAccountID(const uint160& hash160In);
|
||||
|
||||
bool setAccountPublic(const std::string& strPublic);
|
||||
void setAccountPublic(const std::vector<unsigned char>& vPublic);
|
||||
void setAccountPublic(const NewcoinAddress& generator, int seq);
|
||||
|
||||
bool setAccountPrivate(const std::string& strPrivate);
|
||||
void setAccountPrivate(uint256 hash256);
|
||||
|
||||
//
|
||||
// Family Generators
|
||||
//
|
||||
BIGNUM* getFamilyGeneratorBN() const;
|
||||
const std::vector<unsigned char>& getFamilyGenerator() const;
|
||||
|
||||
std::string humanFamilyGenerator() const;
|
||||
|
||||
bool setFamilyGenerator(const std::string& strGenerator);
|
||||
void setFamilyGenerator(const std::vector<unsigned char>& vPublic);
|
||||
void setFamilyGenerator(const NewcoinAddress& seed);
|
||||
|
||||
//
|
||||
// Family Seeds
|
||||
//
|
||||
uint128 getFamilySeed() const;
|
||||
BIGNUM* getFamilyPrivateKey() const;
|
||||
std::string humanFamilySeed() const;
|
||||
bool setFamilySeed(const std::string& strSeed);
|
||||
void setFamilySeed(uint128 hash128);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
#include "boost/interprocess/sync/scoped_lock.hpp"
|
||||
|
||||
|
||||
CKey::pointer PubKeyCache::locate(const uint160& id)
|
||||
CKey::pointer PubKeyCache::locate(const NewcoinAddress& id)
|
||||
{
|
||||
if(1)
|
||||
{ // is it in cache
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, CKey::pointer>::iterator it(mCache.find(id));
|
||||
std::map<NewcoinAddress, CKey::pointer>::iterator it(mCache.find(id));
|
||||
if(it!=mCache.end()) return it->second;
|
||||
}
|
||||
|
||||
std::string sql="SELECT * from PubKeys WHERE ID='";
|
||||
sql.append(id.GetHex());
|
||||
sql.append(id.humanAccountID());
|
||||
sql.append("';'");
|
||||
std::vector<unsigned char> data;
|
||||
data.reserve(65); // our public keys are actually 33 bytes
|
||||
@@ -44,17 +44,17 @@ CKey::pointer PubKeyCache::locate(const uint160& id)
|
||||
return ckp;
|
||||
}
|
||||
|
||||
CKey::pointer PubKeyCache::store(const uint160& id, CKey::pointer key)
|
||||
CKey::pointer PubKeyCache::store(const NewcoinAddress& id, CKey::pointer key)
|
||||
{ // stored if needed, returns cached copy (possibly the original)
|
||||
if(1)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
std::pair<std::map<uint160,CKey::pointer>::iterator, bool> pit(mCache.insert(std::make_pair(id, key)));
|
||||
std::pair<std::map<NewcoinAddress,CKey::pointer>::iterator, bool> pit(mCache.insert(std::make_pair(id, key)));
|
||||
if(!pit.second) // there was an existing key
|
||||
return pit.first->second;
|
||||
}
|
||||
std::string sql="INSERT INTO PubKeys (ID,PubKey) VALUES ('";
|
||||
sql+=id.GetHex();
|
||||
sql+=id.humanAccountID();
|
||||
sql+="',";
|
||||
|
||||
std::vector<unsigned char> pk=key->GetPubKey();
|
||||
|
||||
@@ -5,20 +5,20 @@
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include "uint256.h"
|
||||
#include "NewcoinAddress.h"
|
||||
#include "key.h"
|
||||
|
||||
class PubKeyCache
|
||||
{
|
||||
private:
|
||||
boost::mutex mLock;
|
||||
std::map<uint160, CKey::pointer> mCache;
|
||||
std::map<NewcoinAddress, CKey::pointer> mCache;
|
||||
|
||||
public:
|
||||
PubKeyCache() { ; }
|
||||
|
||||
CKey::pointer locate(const uint160& id);
|
||||
CKey::pointer store(const uint160& id, CKey::pointer key);
|
||||
CKey::pointer locate(const NewcoinAddress& id);
|
||||
CKey::pointer store(const NewcoinAddress& id, CKey::pointer key);
|
||||
void clear();
|
||||
};
|
||||
|
||||
|
||||
@@ -154,47 +154,60 @@ bool RPCServer::extractString(std::string& param, const Json::Value& params, int
|
||||
return true;
|
||||
}
|
||||
|
||||
uint160 RPCServer::parseFamily(const std::string& fParam)
|
||||
NewcoinAddress RPCServer::parseFamily(const std::string& fParam)
|
||||
{
|
||||
uint160 family;
|
||||
if(Wallet::isHexFamily(fParam))
|
||||
family.SetHex(fParam);
|
||||
else if(Wallet::isHexPublicKey(fParam))
|
||||
family=theApp->getWallet().findFamilyPK(fParam);
|
||||
else
|
||||
family=theApp->getWallet().findFamilySN(fParam);
|
||||
NewcoinAddress family;
|
||||
|
||||
if(family.setFamilyGenerator(fParam))
|
||||
{
|
||||
family = theApp->getWallet().findFamilyPK(family);
|
||||
}
|
||||
|
||||
return family;
|
||||
}
|
||||
|
||||
Json::Value RPCServer::doCreateFamily(Json::Value& params)
|
||||
{
|
||||
// createfamily <hexPrivateKey>
|
||||
// createfamily <hexPublicKey>
|
||||
// createfamily FXXXX
|
||||
// createfamily fXXXX
|
||||
// createfamily "<pass phrase>"
|
||||
// createfamily
|
||||
|
||||
std::string query;
|
||||
uint160 family;
|
||||
NewcoinAddress family;
|
||||
NewcoinAddress seed;
|
||||
|
||||
uint256 privKey;
|
||||
if(!extractString(query, params, 0))
|
||||
family=theApp->getWallet().addRandomFamily(privKey);
|
||||
else if(Wallet::isHexPrivateKey(query))
|
||||
family=theApp->getWallet().addFamily(Wallet::textToPrivKey(query), false);
|
||||
else if(Wallet::isHexPublicKey(query))
|
||||
family=theApp->getWallet().addFamily(query);
|
||||
{
|
||||
// No parameters, generate a family from a random seed.
|
||||
family=theApp->getWallet().addRandomFamily(seed);
|
||||
}
|
||||
else if(seed.setFamilySeed(query))
|
||||
{
|
||||
// Had a family seed.
|
||||
family=theApp->getWallet().addFamily(seed, false);
|
||||
}
|
||||
else if(family.setFamilyGenerator(query))
|
||||
{
|
||||
// Had a public generator
|
||||
family=theApp->getWallet().addFamily(family);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Must be a pass phrase.
|
||||
family=theApp->getWallet().addFamily(query, false);
|
||||
if(!family)
|
||||
}
|
||||
|
||||
if(!family.IsValid())
|
||||
return JSONRPCError(500, "Invalid family specifier");
|
||||
|
||||
Json::Value ret(theApp->getWallet().getFamilyJson(family));
|
||||
if(ret.isNull()) return JSONRPCError(500, "Invalid family");
|
||||
if(!!privKey)
|
||||
if(seed.IsValid())
|
||||
{
|
||||
ret["PrivateGenerator"]=Wallet::privKeyToText(privKey);
|
||||
privKey.zero();
|
||||
ret["FamilySeed"]=seed.humanFamilySeed();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -208,14 +221,9 @@ Json::Value RPCServer::doAccountInfo(Json::Value ¶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,8 +234,9 @@ 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;
|
||||
}
|
||||
@@ -238,12 +247,13 @@ Json::Value RPCServer::doNewAccount(Json::Value ¶ms)
|
||||
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 <family>
|
||||
// lock
|
||||
std::string fParam;
|
||||
|
||||
if(extractString(fParam, params, 0))
|
||||
{ // local <family>
|
||||
uint160 family = parseFamily(fParam);
|
||||
if(!family) return JSONRPCError(500, "Family not found");
|
||||
NewcoinAddress family = parseFamily(fParam);
|
||||
if(!family.IsValid()) return JSONRPCError(500, "Family not found");
|
||||
|
||||
theApp->getWallet().lock(family);
|
||||
return "locked";
|
||||
}
|
||||
else
|
||||
{
|
||||
theApp->getWallet().lock();
|
||||
return "locked";
|
||||
}
|
||||
|
||||
return "locked";
|
||||
}
|
||||
|
||||
Json::Value RPCServer::doUnlock(Json::Value ¶ms)
|
||||
{ // unlock <hexPrivateKey>
|
||||
{ // unlock FXXXX
|
||||
// unlock "<pass phrase>"
|
||||
|
||||
std::string param;
|
||||
if(!extractString(param, params, 0) || Wallet::isHexPublicKey(param))
|
||||
NewcoinAddress familyGenerator;
|
||||
|
||||
if(!extractString(param, params, 0) || familyGenerator.setFamilyGenerator(param))
|
||||
return JSONRPCError(500, "Private key required");
|
||||
|
||||
uint160 family;
|
||||
if(Wallet::isHexPrivateKey(param))
|
||||
family=theApp->getWallet().addFamily(Wallet::textToPrivKey(param), false);
|
||||
NewcoinAddress family;
|
||||
NewcoinAddress familySeed;
|
||||
|
||||
if(familySeed.setFamilySeed(param))
|
||||
// FXXX
|
||||
family=theApp->getWallet().addFamily(familySeed, false);
|
||||
else
|
||||
// pass phrase
|
||||
family=theApp->getWallet().addFamily(param, false);
|
||||
|
||||
if(!family)
|
||||
if(!family.IsValid())
|
||||
return JSONRPCError(500, "Bad family");
|
||||
|
||||
Json::Value ret(theApp->getWallet().getFamilyJson(family));
|
||||
if(ret.isNull()) return JSONRPCError(500, "Invalid family");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -295,11 +315,11 @@ Json::Value RPCServer::doFamilyInfo(Json::Value ¶ms)
|
||||
|
||||
if(paramCount==0)
|
||||
{
|
||||
std::vector<uint160> familyIDs;
|
||||
std::vector<NewcoinAddress> familyIDs;
|
||||
theApp->getWallet().getFamilies(familyIDs);
|
||||
|
||||
Json::Value ret(Json::arrayValue);
|
||||
BOOST_FOREACH(const uint160& fid, familyIDs)
|
||||
BOOST_FOREACH(const NewcoinAddress& fid, familyIDs)
|
||||
{
|
||||
Json::Value obj(theApp->getWallet().getFamilyJson(fid));
|
||||
if(!obj.isNull()) ret.append(obj);
|
||||
@@ -311,8 +331,9 @@ Json::Value RPCServer::doFamilyInfo(Json::Value ¶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<int>(keyNum);
|
||||
uint160 k=theApp->getWallet().peekKey(family, kn);
|
||||
if(!!k)
|
||||
NewcoinAddress k=theApp->getWallet().peekKey(family, kn);
|
||||
|
||||
if(k.IsValid())
|
||||
{
|
||||
Json::Value key(Json::objectValue);
|
||||
key["Number"]=kn;
|
||||
key["Address"]=NewcoinAddress(k).GetString();
|
||||
key["Address"]=k.humanAccountID();
|
||||
obj["Account"]=key;
|
||||
}
|
||||
}
|
||||
@@ -370,8 +392,8 @@ Json::Value RPCServer::doSendTo(Json::Value& params)
|
||||
if(!extractString(sDest, params, 0) || !extractString(sAmount, params, 1))
|
||||
return JSONRPCError(500, "Invalid parameters");
|
||||
|
||||
uint160 destAccount=parseAccount(sDest);
|
||||
if(!destAccount)
|
||||
NewcoinAddress destAccount = parseAccount(sDest);
|
||||
if(!destAccount.IsValid())
|
||||
return JSONRPCError(500, "Unable to parse destination account");
|
||||
|
||||
uint64 iAmount;
|
||||
@@ -401,7 +423,7 @@ Json::Value RPCServer::doSendTo(Json::Value& params)
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "SendTo(" << destAccount.GetHex() << ") amount=" << iAmount <<
|
||||
std::cerr << "SendTo(" << destAccount.humanAccountID() << ") amount=" << iAmount <<
|
||||
", tag=" << iTag << std::endl;
|
||||
#endif
|
||||
|
||||
@@ -476,6 +498,39 @@ Json::Value RPCServer::doLedger(Json::Value& params)
|
||||
return "not implemented";
|
||||
}
|
||||
|
||||
Json::Value RPCServer::doAddUnl(Json::Value& params) {
|
||||
// addUNL <node_public>
|
||||
// addUNL <node_public> <comment>
|
||||
if(params.size()==1 || params.size()==2)
|
||||
{
|
||||
std::string pubKey=params[0u].asString();
|
||||
std::string comment=params.size() == 2
|
||||
? ""
|
||||
: params[1u].asString();
|
||||
|
||||
NewcoinAddress nodePublic;
|
||||
|
||||
if(nodePublic.setNodePublic(pubKey))
|
||||
{
|
||||
theApp->getUNL().addNode(nodePublic, comment);
|
||||
|
||||
return "adding node";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "invalid public key";
|
||||
}
|
||||
}
|
||||
else return "invalid params";
|
||||
}
|
||||
|
||||
Json::Value RPCServer::doGetUnl(Json::Value& params) {
|
||||
std::string str;
|
||||
theApp->getUNL().dumpUNL(str);
|
||||
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params)
|
||||
{
|
||||
std::cerr << "RPC:" << command << std::endl;
|
||||
@@ -484,24 +539,8 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
|
||||
mSocket.get_io_service().stop();
|
||||
return "newcoin server stopping";
|
||||
}
|
||||
if(command== "addUNL")
|
||||
{
|
||||
if(params.size()==2)
|
||||
{
|
||||
uint160 hanko=humanTo160(params[0u].asString());
|
||||
std::vector<unsigned char> pubKey;
|
||||
humanToPK(params[1u].asString(),pubKey);
|
||||
theApp->getUNL().addNode(hanko,pubKey);
|
||||
return "adding node";
|
||||
}
|
||||
else return "invalid params";
|
||||
}
|
||||
if(command=="getUNL")
|
||||
{
|
||||
std::string str;
|
||||
theApp->getUNL().dumpUNL(str);
|
||||
return(str.c_str());
|
||||
}
|
||||
if(command=="addUNL") return doAddUnl(params);
|
||||
if(command=="getUNL") return doGetUnl(params);
|
||||
if(command=="createfamily") return doCreateFamily(params);
|
||||
if(command=="familyinfo") return doFamilyInfo(params);
|
||||
if(command=="accountinfo") return doAccountInfo(params);
|
||||
@@ -526,19 +565,23 @@ void RPCServer::sendReply()
|
||||
|
||||
void RPCServer::handle_write(const boost::system::error_code& /*error*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint160 RPCServer::parseAccount(const std::string& account)
|
||||
NewcoinAddress RPCServer::parseAccount(const std::string& account)
|
||||
{ // FIXME: Support local wallet key names
|
||||
if(account.find(':')!=std::string::npos)
|
||||
{ // local account in family:seq form
|
||||
LocalAccount::pointer lac(theApp->getWallet().parseAccount(account));
|
||||
if(!lac) return uint160();
|
||||
return lac->getAddress();
|
||||
|
||||
return lac
|
||||
? lac->getAddress()
|
||||
: NewcoinAddress();
|
||||
}
|
||||
|
||||
NewcoinAddress nac(account);
|
||||
if(!nac.IsValid()) return uint160();
|
||||
return nac.GetHash160();
|
||||
NewcoinAddress *nap = new NewcoinAddress();
|
||||
|
||||
nap->setAccountID(account) || nap->setAccountPublic(account);
|
||||
|
||||
return *nap;
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "HttpRequest.h"
|
||||
#include "RequestParser.h"
|
||||
#include "uint256.h"
|
||||
#include "NewcoinAddress.h"
|
||||
|
||||
class RPCServer : public boost::enable_shared_from_this<RPCServer>
|
||||
{
|
||||
@@ -31,7 +31,7 @@ class RPCServer : public boost::enable_shared_from_this<RPCServer>
|
||||
int getParamCount(const Json::Value& params);
|
||||
bool extractString(std::string& param, const Json::Value& params, int index);
|
||||
|
||||
uint160 parseFamily(const std::string& family);
|
||||
NewcoinAddress parseFamily(const std::string& family);
|
||||
|
||||
Json::Value doCreateFamily(Json::Value& params);
|
||||
Json::Value doFamilyInfo(Json::Value& params);
|
||||
@@ -45,10 +45,11 @@ class RPCServer : public boost::enable_shared_from_this<RPCServer>
|
||||
Json::Value doTx(Json::Value& params);
|
||||
Json::Value doLedger(Json::Value& params);
|
||||
Json::Value doAccount(Json::Value& params);
|
||||
Json::Value doAddUnl(Json::Value& params);
|
||||
Json::Value doGetUnl(Json::Value& params);
|
||||
|
||||
// parses a string account name into a uint160
|
||||
// can be local or remote
|
||||
uint160 parseAccount(const std::string& account);
|
||||
// Parses a string account name into a local or remote NewcoinAddress.
|
||||
NewcoinAddress parseAccount(const std::string& account);
|
||||
|
||||
public:
|
||||
typedef boost::shared_ptr<RPCServer> pointer;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -30,6 +30,7 @@ class Serializer
|
||||
int add16(uint16);
|
||||
int add32(uint32); // ledger indexes, account sequence
|
||||
int add64(uint64); // timestamps, amounts
|
||||
int add128(const uint128&); // private key generators
|
||||
int add160(const uint160&); // account names, hankos
|
||||
int add256(const uint256&); // transaction and ledger hashes
|
||||
int addRaw(const std::vector<unsigned char> &vector);
|
||||
@@ -120,3 +121,4 @@ public:
|
||||
};
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
Transaction::Transaction() : mTransactionID(0), mAccountFrom(0), mAccountTo(0),
|
||||
Transaction::Transaction() : mTransactionID(0), mAccountFrom(), mAccountTo(),
|
||||
mAmount(0), mFee(0), mFromAccountSeq(0), mSourceLedger(0), mIdent(0),
|
||||
mInLedger(0), mStatus(INVALID)
|
||||
{
|
||||
}
|
||||
|
||||
Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const uint160& toAccount, uint64 amount,
|
||||
Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAddress& toAccount, uint64 amount,
|
||||
uint32 ident, uint32 ledger) :
|
||||
mAccountTo(toAccount), mAmount(amount), mSourceLedger(ledger), mIdent(ident), mInLedger(0), mStatus(NEW)
|
||||
{
|
||||
@@ -52,9 +52,12 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const uint160&
|
||||
|
||||
Transaction::Transaction(const std::vector<unsigned char> &t, bool validate) : mStatus(INVALID)
|
||||
{
|
||||
uint160 toAccountID;
|
||||
uint160 fromAccountID;
|
||||
|
||||
Serializer s(t);
|
||||
if(s.getLength()<BTxSize) { assert(false); return; }
|
||||
if(!s.get160(mAccountTo, BTxPDestAcct)) { assert(false); return; }
|
||||
if(!s.get160(toAccountID, BTxPDestAcct)) { assert(false); return; }
|
||||
if(!s.get64(mAmount, BTxPAmount)) { assert(false); return; }
|
||||
if(!s.get32(mFromAccountSeq, BTxPSASeq)) { assert(false); return; }
|
||||
if(!s.get32(mSourceLedger, BTxPSLIdx)) { assert(false); return; }
|
||||
@@ -63,9 +66,13 @@ Transaction::Transaction(const std::vector<unsigned char> &t, bool validate) : m
|
||||
|
||||
std::vector<unsigned char> pubKey;
|
||||
if(!s.getRaw(pubKey, BTxPSPubK, BTxLSPubK)) { assert(false); return; }
|
||||
|
||||
mAccountTo.setAccountID(toAccountID);
|
||||
mAccountFrom.setAccountID(fromAccountID);
|
||||
|
||||
mFromPubKey=boost::make_shared<CKey>();
|
||||
if(!mFromPubKey->SetPubKey(pubKey)) return;
|
||||
mAccountFrom=Hash160(pubKey);
|
||||
mAccountFrom.setAccountPublic(pubKey);
|
||||
mFromPubKey=theApp->getPubKeyCache().store(mAccountFrom, mFromPubKey);
|
||||
|
||||
updateID();
|
||||
@@ -86,7 +93,7 @@ bool Transaction::sign(LocalAccount::pointer fromLocalAccount)
|
||||
return false;
|
||||
}
|
||||
|
||||
if( (mAmount==0) || (mSourceLedger==0) || (mAccountTo==0) )
|
||||
if( (mAmount==0) || (mSourceLedger==0) || !mAccountTo.IsValid() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Bad amount, source ledger, or destination" << std::endl;
|
||||
@@ -94,7 +101,8 @@ bool Transaction::sign(LocalAccount::pointer fromLocalAccount)
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
if(mAccountFrom!=fromLocalAccount->getAddress())
|
||||
|
||||
if(mAccountFrom.getAccountID()!=fromLocalAccount->getAddress().getAccountID())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Source mismatch" << std::endl;
|
||||
@@ -129,9 +137,11 @@ bool Transaction::checkSign() const
|
||||
|
||||
Serializer::pointer Transaction::getRaw(bool prefix) const
|
||||
{
|
||||
uint160 toAccountID = mAccountTo.getAccountID();
|
||||
|
||||
Serializer::pointer ret=boost::make_shared<Serializer>(77);
|
||||
if(prefix) ret->add32(0x54584e00u);
|
||||
ret->add160(mAccountTo);
|
||||
ret->add160(toAccountID);
|
||||
ret->add64(mAmount);
|
||||
ret->add32(mFromAccountSeq);
|
||||
ret->add32(mSourceLedger);
|
||||
@@ -174,7 +184,7 @@ bool Transaction::save() const
|
||||
" VALUES ('";
|
||||
sql.append(mTransactionID.GetHex());
|
||||
sql.append("','");
|
||||
sql.append(mAccountFrom.GetHex());
|
||||
sql.append(mAccountFrom.humanAccountID());
|
||||
sql.append("','");
|
||||
sql.append(boost::lexical_cast<std::string>(mFromAccountSeq));
|
||||
sql.append("','");
|
||||
@@ -182,7 +192,7 @@ bool Transaction::save() const
|
||||
sql.append("','");
|
||||
sql.append(boost::lexical_cast<std::string>(mIdent));
|
||||
sql.append("','");
|
||||
sql.append(mAccountTo.GetHex());
|
||||
sql.append(mAccountTo.humanAccountID());
|
||||
sql.append("','");
|
||||
sql.append(boost::lexical_cast<std::string>(mAmount));
|
||||
sql.append("','");
|
||||
@@ -238,10 +248,10 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
|
||||
}
|
||||
|
||||
uint256 trID;
|
||||
uint160 frID, tID;
|
||||
NewcoinAddress frID, tID;
|
||||
trID.SetHex(transID);
|
||||
frID.SetHex(fromID);
|
||||
tID.SetHex(toID);
|
||||
frID.setAccountID(fromID);
|
||||
tID.setAccountID(toID);
|
||||
|
||||
CKey::pointer pubkey=theApp->getPubKeyCache().locate(frID);
|
||||
if(!pubkey) return Transaction::pointer();
|
||||
@@ -269,10 +279,10 @@ Transaction::pointer Transaction::load(const uint256& id)
|
||||
return transactionFromSQL(sql);
|
||||
}
|
||||
|
||||
Transaction::pointer Transaction::findFrom(const uint160& fromID, uint32 seq)
|
||||
Transaction::pointer Transaction::findFrom(const NewcoinAddress& fromID, uint32 seq)
|
||||
{
|
||||
std::string sql="SELECT * FROM Transactions WHERE FromID='";
|
||||
sql.append(fromID.GetHex());
|
||||
sql.append(fromID.humanAccountID());
|
||||
sql.append("' AND FromSeq='");
|
||||
sql.append(boost::lexical_cast<std::string>(seq));
|
||||
sql.append("';");
|
||||
@@ -361,13 +371,14 @@ Json::Value Transaction::getJson(bool decorate, bool paid, bool credited) const
|
||||
}
|
||||
|
||||
Json::Value source(Json::objectValue);
|
||||
source["AccountID"]=NewcoinAddress(mAccountFrom).GetString();
|
||||
|
||||
source["AccountID"]=mAccountFrom.humanAccountID();
|
||||
source["AccountSeq"]=mFromAccountSeq;
|
||||
source["Ledger"]=mSourceLedger;
|
||||
if(!!mIdent) source["Identifier"]=mIdent;
|
||||
|
||||
Json::Value destination(Json::objectValue);
|
||||
destination["AccountID"]=NewcoinAddress(mAccountTo).GetString();
|
||||
destination["AccountID"]=mAccountTo.humanAccountID();
|
||||
|
||||
if(decorate)
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
private:
|
||||
uint256 mTransactionID;
|
||||
uint160 mAccountFrom, mAccountTo;
|
||||
NewcoinAddress mAccountFrom, mAccountTo;
|
||||
uint64 mAmount, mFee;
|
||||
uint32 mFromAccountSeq, mSourceLedger, mIdent;
|
||||
CKey::pointer mFromPubKey;
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
public:
|
||||
Transaction();
|
||||
Transaction(const std::vector<unsigned char>& rawTransaction, bool validate);
|
||||
Transaction(LocalAccount::pointer fromLocal, const uint160& to, uint64 amount, uint32 ident, uint32 ledger);
|
||||
Transaction(LocalAccount::pointer fromLocal, const NewcoinAddress& to, uint64 amount, uint32 ident, uint32 ledger);
|
||||
|
||||
bool sign(LocalAccount::pointer fromLocalAccount);
|
||||
bool checkSign() const;
|
||||
@@ -67,8 +67,8 @@ public:
|
||||
Serializer::pointer getSigned() const;
|
||||
|
||||
const uint256& getID() const { return mTransactionID; }
|
||||
const uint160& getFromAccount() const { return mAccountFrom; }
|
||||
const uint160& getToAccount() const { return mAccountTo; }
|
||||
const NewcoinAddress& getFromAccount() const { return mAccountFrom; }
|
||||
const NewcoinAddress& getToAccount() const { return mAccountTo; }
|
||||
uint64 getAmount() const { return mAmount; }
|
||||
uint64 getFee() const { return mFee; }
|
||||
uint32 getFromAccountSeq() const { return mFromAccountSeq; }
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
static void saveTransaction(Transaction::pointer);
|
||||
bool save() const;
|
||||
static Transaction::pointer load(const uint256& id);
|
||||
static Transaction::pointer findFrom(const uint160& fromID, uint32 seq);
|
||||
static Transaction::pointer findFrom(const NewcoinAddress& fromID, uint32 seq);
|
||||
|
||||
// conversion function
|
||||
static bool convertToTransactions(uint32 ourLedgerSeq, uint32 otherLedgerSeq,
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
|
||||
protected:
|
||||
static Transaction::pointer transactionFromSQL(const std::string& statement);
|
||||
Transaction(const uint256& transactionID, const uint160& accountFrom, const uint160& accountTo,
|
||||
Transaction(const uint256& transactionID, const NewcoinAddress& accountFrom, const NewcoinAddress& accountTo,
|
||||
CKey::pointer key, uint64 amount, uint64 fee, uint32 fromAccountSeq, uint32 sourceLedger,
|
||||
uint32 ident, const std::vector<unsigned char>& signature, uint32 inLedger, TransStatus status) :
|
||||
mTransactionID(transactionID), mAccountFrom(accountFrom), mAccountTo(accountTo),
|
||||
@@ -116,3 +116,4 @@ protected:
|
||||
};
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
|
||||
@@ -2,31 +2,40 @@
|
||||
#include "Application.h"
|
||||
#include "Conversion.h"
|
||||
|
||||
void UniqueNodeList::addNode(uint160& hanko, std::vector<unsigned char>& publicKey)
|
||||
void UniqueNodeList::addNode(NewcoinAddress address,std::string comment)
|
||||
{
|
||||
Database* db=theApp->getNetNodeDB()->getDB();
|
||||
std::string sql="INSERT INTO UNL (Hanko,PubKey) values (";
|
||||
std::string hashStr;
|
||||
db->escape(hanko.begin(), hanko.GetSerializeSize(), hashStr);
|
||||
sql.append(hashStr);
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
|
||||
// void UniqueNodeList::addNode(uint160& hanko, std::vector<unsigned char>& publicKey,std::string comment)
|
||||
|
||||
std::string hanko = address.humanHanko();
|
||||
std::string publicKey = address.humanNodePublic();
|
||||
|
||||
std::string sql="INSERT INTO TrustedNodes (Hanko,PubKey,Comment) values (";
|
||||
std::string tmpStr;
|
||||
db->escape(reinterpret_cast<const unsigned char*>(hanko.c_str()), hanko.size(), tmpStr);
|
||||
sql.append(tmpStr);
|
||||
sql.append(",");
|
||||
db->escape(&(publicKey[0]), publicKey.size(), hashStr);
|
||||
sql.append(hashStr);
|
||||
db->escape(reinterpret_cast<const unsigned char*>(publicKey.c_str()), publicKey.size(), tmpStr);
|
||||
sql.append(tmpStr);
|
||||
sql.append(",");
|
||||
db->escape(reinterpret_cast<const unsigned char*>(comment.c_str()), comment.size(), tmpStr);
|
||||
sql.append(tmpStr);
|
||||
sql.append(")");
|
||||
|
||||
ScopedLock sl(theApp->getNetNodeDB()->getDBLock());
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
db->executeSQL(sql.c_str());
|
||||
}
|
||||
|
||||
void UniqueNodeList::removeNode(uint160& hanko)
|
||||
{
|
||||
Database* db=theApp->getNetNodeDB()->getDB();
|
||||
std::string sql="DELETE FROM UNL where hanko=";
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
std::string sql="DELETE FROM TrustedNodes where hanko=";
|
||||
std::string hashStr;
|
||||
db->escape(hanko.begin(), hanko.GetSerializeSize(), hashStr);
|
||||
sql.append(hashStr);
|
||||
|
||||
ScopedLock sl(theApp->getNetNodeDB()->getDBLock());
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
db->executeSQL(sql.c_str());
|
||||
}
|
||||
|
||||
@@ -34,13 +43,13 @@ void UniqueNodeList::removeNode(uint160& hanko)
|
||||
#if 0
|
||||
int UniqueNodeList::checkValid(newcoin::Validation& valid)
|
||||
{
|
||||
Database* db=theApp->getNetNodeDB()->getDB();
|
||||
std::string sql="SELECT pubkey from UNL where hanko=";
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
std::string sql="SELECT pubkey from TrustedNodes where hanko=";
|
||||
std::string hashStr;
|
||||
db->escape((unsigned char*) &(valid.hanko()[0]),valid.hanko().size(),hashStr);
|
||||
sql.append(hashStr);
|
||||
|
||||
ScopedLock sl(theApp->getNetNodeDB()->getDBLock());
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
if( db->executeSQL(sql.c_str()) )
|
||||
{
|
||||
if(db->startIterRows() && db->getNextRow())
|
||||
@@ -59,10 +68,12 @@ int UniqueNodeList::checkValid(newcoin::Validation& valid)
|
||||
|
||||
void UniqueNodeList::dumpUNL(std::string& retStr)
|
||||
{
|
||||
Database* db=theApp->getNetNodeDB()->getDB();
|
||||
std::string sql="SELECT * FROM UNL;";
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
std::string sql="SELECT * FROM TrustedNodes;";
|
||||
|
||||
ScopedLock sl(theApp->getNetNodeDB()->getDBLock());
|
||||
retStr.append("hello\n");
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
if( db->executeSQL(sql.c_str()) )
|
||||
{
|
||||
db->startIterRows();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define __UNIQUE_NODE_LIST__
|
||||
#include "../obj/src/newcoin.pb.h"
|
||||
#include "uint256.h"
|
||||
#include "NewcoinAddress.h"
|
||||
|
||||
class UniqueNodeList
|
||||
{
|
||||
@@ -11,15 +12,13 @@ public:
|
||||
//void load();
|
||||
//void save();
|
||||
|
||||
void addNode(uint160& hanko,std::vector<unsigned char>& publicKey);
|
||||
void addNode(NewcoinAddress address,std::string comment);
|
||||
void removeNode(uint160& hanko);
|
||||
|
||||
// 0- we don't care, 1- we care and is valid, 2-invalid signature
|
||||
// int checkValid(newcoin::Validation& valid);
|
||||
|
||||
void dumpUNL(std::string& retStr);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "ValidationCollection.h"
|
||||
#include "Application.h"
|
||||
#include "NewcoinAddress.h"
|
||||
#include "Config.h"
|
||||
#include "Conversion.h"
|
||||
#include "Application.h"
|
||||
|
||||
449
src/Wallet.cpp
449
src/Wallet.cpp
@@ -21,38 +21,34 @@
|
||||
#define CHECK_NEW_FAMILIES 500
|
||||
#endif
|
||||
|
||||
//
|
||||
// LocalAccount - an account
|
||||
//
|
||||
|
||||
LocalAccount::LocalAccount(boost::shared_ptr<LocalAccountFamily> family, int familySeq) :
|
||||
mPublicKey(family->getPublicKey(familySeq)), mFamily(family), mAccountFSeq(familySeq),
|
||||
mLgrBalance(0), mTxnDelta(0), mTxnSeq(0)
|
||||
{
|
||||
mAcctID=mPublicKey->GetAddress().GetHash160();
|
||||
mAcctID=mPublicKey->GetAddress();
|
||||
|
||||
if(theApp!=NULL) mPublicKey=theApp->getPubKeyCache().store(mAcctID, mPublicKey);
|
||||
}
|
||||
|
||||
std::string LocalAccount::getAccountName() const
|
||||
{
|
||||
return mPublicKey->GetAddress().GetString();
|
||||
}
|
||||
//
|
||||
// LocalAccountFamily - a sequences of accounts
|
||||
//
|
||||
|
||||
std::string LocalAccount::getLocalAccountName() const
|
||||
{
|
||||
return NewcoinAddress(mFamily->getFamily()).GetString() + ":" + boost::lexical_cast<std::string>(mAccountFSeq);
|
||||
}
|
||||
|
||||
LocalAccountFamily::LocalAccountFamily(const uint160& family, const EC_GROUP* group, const EC_POINT* pubKey) :
|
||||
LocalAccountFamily::LocalAccountFamily(const NewcoinAddress& family) :
|
||||
mFamily(family), mLastSeq(0), mRootPrivateKey(NULL)
|
||||
{
|
||||
mRootPubKey=EC_POINT_dup(pubKey, group);
|
||||
mName=family.GetHex().substr(0, 4);
|
||||
}
|
||||
|
||||
LocalAccountFamily::~LocalAccountFamily()
|
||||
{
|
||||
lock();
|
||||
if(mRootPubKey!=NULL) EC_POINT_free(mRootPubKey);
|
||||
}
|
||||
|
||||
uint160 LocalAccountFamily::getAccount(int seq, bool keep)
|
||||
NewcoinAddress LocalAccountFamily::getAccount(int seq, bool keep)
|
||||
{
|
||||
std::map<int, LocalAccount::pointer>::iterator ait=mAccounts.find(seq);
|
||||
if(ait!=mAccounts.end()) return ait->second->getAddress();
|
||||
@@ -63,15 +59,15 @@ uint160 LocalAccountFamily::getAccount(int seq, bool keep)
|
||||
return lae->getAddress();
|
||||
}
|
||||
|
||||
void LocalAccountFamily::unlock(const BIGNUM* privateKey)
|
||||
void LocalAccountFamily::unlock(BIGNUM* privateKey)
|
||||
{
|
||||
if(mRootPrivateKey==NULL) mRootPrivateKey=BN_dup(privateKey);
|
||||
if(mRootPrivateKey==NULL) mRootPrivateKey=privateKey;
|
||||
|
||||
#ifdef CHECK_NEW_FAMILIES
|
||||
std::cerr << "CheckingFamily" << std::endl;
|
||||
for(int i=0; i<CHECK_NEW_FAMILIES; i++)
|
||||
{
|
||||
EC_KEY *pubkey=CKey::GeneratePublicDeterministicKey(mFamily, mRootPubKey, i);
|
||||
EC_KEY *pubkey=CKey::GeneratePublicDeterministicKey(mFamily, i);
|
||||
EC_KEY *privkey=CKey::GeneratePrivateDeterministicKey(mFamily, mRootPrivateKey, i);
|
||||
|
||||
int cmp=EC_POINT_cmp(EC_KEY_get0_group(pubkey), EC_KEY_get0_public_key(pubkey),
|
||||
@@ -79,7 +75,7 @@ void LocalAccountFamily::unlock(const BIGNUM* privateKey)
|
||||
if(cmp!=0)
|
||||
{
|
||||
std::cerr << BN_bn2hex(mRootPrivateKey) << std::endl;
|
||||
std::cerr << "family=" << mFamily.GetHex() << std::endl;
|
||||
std::cerr << "family=" << mFamily.humanFamilyGenerator() << std::endl;
|
||||
std::cerr << "i=" << i << std::endl;
|
||||
std::cerr << "Key mismatch" << std::endl;
|
||||
assert(false);
|
||||
@@ -102,61 +98,32 @@ void LocalAccountFamily::lock()
|
||||
|
||||
CKey::pointer LocalAccountFamily::getPublicKey(int seq)
|
||||
{
|
||||
return boost::make_shared<CKey>(mFamily, mRootPubKey, seq);
|
||||
return boost::make_shared<CKey>(mFamily, seq);
|
||||
}
|
||||
|
||||
CKey::pointer LocalAccountFamily::getPrivateKey(int seq)
|
||||
{
|
||||
if(!mRootPrivateKey) return CKey::pointer();
|
||||
std::cerr << "PrivKey(" << mFamily.GetHex() << "," << seq << ")" << std::endl;
|
||||
std::cerr << "PrivKey(" << mFamily.humanFamilyGenerator() << "," << seq << ")" << std::endl;
|
||||
return boost::make_shared<CKey>(mFamily, mRootPrivateKey, seq);
|
||||
}
|
||||
|
||||
std::string LocalAccountFamily::getPubGenHex() const
|
||||
{
|
||||
EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
if(!grp) return "";
|
||||
|
||||
BIGNUM* pubBase=EC_POINT_point2bn(grp, mRootPubKey, POINT_CONVERSION_COMPRESSED, NULL, NULL);
|
||||
EC_GROUP_free(grp);
|
||||
|
||||
if(!pubBase) return "";
|
||||
char *hex=BN_bn2hex(pubBase);
|
||||
BN_free(pubBase);
|
||||
|
||||
if(!hex) return "";
|
||||
std::string ret(hex);
|
||||
OPENSSL_free(hex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool isHex(char j)
|
||||
{
|
||||
if((j>='0') && (j<='9')) return true;
|
||||
if((j>='A') && (j<='F')) return true;
|
||||
if((j>='a') && (j<='f')) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Json::Value LocalAccountFamily::getJson() const
|
||||
{
|
||||
Json::Value ret(Json::objectValue);
|
||||
ret["ShortName"]=getShortName();
|
||||
ret["FullName"]=getFamily().GetHex();
|
||||
ret["PublicGenerator"]=getPubGenHex();
|
||||
ret["FullName"]=getFamily().humanFamilyGenerator();
|
||||
ret["IsLocked"]=isLocked();
|
||||
if(!getComment().empty()) ret["Comment"]=getComment();
|
||||
return ret;
|
||||
}
|
||||
|
||||
LocalAccountFamily::pointer LocalAccountFamily::readFamily(const uint160& family)
|
||||
LocalAccountFamily::pointer LocalAccountFamily::readFamily(const NewcoinAddress& family)
|
||||
{
|
||||
std::string sql="SELECT * from LocalAcctFamilies WHERE FamilyName='";
|
||||
sql.append(family.GetHex());
|
||||
std::string sql="SELECT * from LocalAcctFamilies WHERE FamilyGenerator='";
|
||||
sql.append(family.humanFamilyGenerator());
|
||||
sql.append("';");
|
||||
|
||||
std::string rootPubKey, name, comment;
|
||||
std::string comment;
|
||||
uint32 seq;
|
||||
|
||||
if(1)
|
||||
@@ -167,57 +134,39 @@ LocalAccountFamily::pointer LocalAccountFamily::readFamily(const uint160& family
|
||||
if(!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
|
||||
return LocalAccountFamily::pointer();
|
||||
|
||||
db->getStr("RootPubKey", rootPubKey);
|
||||
db->getStr("Name", name);
|
||||
db->getStr("Comment", comment);
|
||||
seq=db->getBigInt("Seq");
|
||||
|
||||
db->endIterRows();
|
||||
}
|
||||
|
||||
EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
if(!grp) return LocalAccountFamily::pointer();
|
||||
LocalAccountFamily::pointer fam=boost::make_shared<LocalAccountFamily>(family);
|
||||
|
||||
EC_POINT *pubKey=EC_POINT_hex2point(grp, rootPubKey.c_str(), NULL, NULL);
|
||||
if(!pubKey)
|
||||
{
|
||||
EC_GROUP_free(grp);
|
||||
assert(false);
|
||||
return LocalAccountFamily::pointer();
|
||||
}
|
||||
|
||||
LocalAccountFamily::pointer fam=boost::make_shared<LocalAccountFamily>(family, grp, pubKey);
|
||||
EC_GROUP_free(grp);
|
||||
EC_POINT_free(pubKey);
|
||||
|
||||
fam->setName(name);
|
||||
fam->setComment(comment);
|
||||
fam->setSeq(seq);
|
||||
|
||||
return fam;
|
||||
}
|
||||
|
||||
void LocalAccountFamily::write(bool is_new)
|
||||
{
|
||||
std::string sql="INSERT INTO LocalAcctFamilies (FamilyName,RootPubKey,Seq,Name,Comment) VALUES ('";
|
||||
sql.append(mFamily.GetHex());
|
||||
std::string sql="INSERT INTO LocalAcctFamilies (FamilyGenerator,Seq,Comment) VALUES ('";
|
||||
sql.append(mFamily.humanFamilyGenerator());
|
||||
sql.append("','");
|
||||
|
||||
EC_GROUP* grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
if(!grp) return;
|
||||
char *rpk=EC_POINT_point2hex(grp, mRootPubKey, POINT_CONVERSION_COMPRESSED, NULL);
|
||||
EC_GROUP_free(grp);
|
||||
if(!rpk) return;
|
||||
sql.append(rpk);
|
||||
OPENSSL_free(rpk);
|
||||
// EC_GROUP* grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
// if(!grp) return;
|
||||
// char *rpk=EC_POINT_point2hex(grp, mRootPubKey, POINT_CONVERSION_COMPRESSED, NULL);
|
||||
// EC_GROUP_free(grp);
|
||||
// if(!rpk) return;
|
||||
// sql.append(rpk);
|
||||
// OPENSSL_free(rpk);
|
||||
// sql.append("','");
|
||||
|
||||
sql.append("','");
|
||||
sql.append(boost::lexical_cast<std::string>(mLastSeq));
|
||||
sql.append("',");
|
||||
|
||||
std::string f;
|
||||
theApp->getWalletDB()->getDB()->escape((const unsigned char *) mName.c_str(), mName.size(), f);
|
||||
sql.append(f);
|
||||
sql.append(",");
|
||||
theApp->getWalletDB()->getDB()->escape((const unsigned char *) mComment.c_str(), mComment.size(), f);
|
||||
sql.append(f);
|
||||
|
||||
@@ -227,67 +176,20 @@ void LocalAccountFamily::write(bool is_new)
|
||||
theApp->getWalletDB()->getDB()->executeSQL(sql.c_str());
|
||||
}
|
||||
|
||||
bool Wallet::isHexPrivateKey(const std::string& s)
|
||||
{ // 65 characters, first is 'P', rest are all legal hex
|
||||
if(s.size()!=65) return false;
|
||||
if(s[0]!='P') return false;
|
||||
for(int i=1; i<65; i++)
|
||||
if(!isHex(s[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Wallet::isHexPublicKey(const std::string& s)
|
||||
{ // 66 characters, all legal hex, starts with '02' or '03'
|
||||
if(s.size()!=66) return false;
|
||||
if(s[0]!='0') return false;
|
||||
if((s[1]!='2') && (s[1]!='3')) return false;
|
||||
for(int i=3; i<66; i++)
|
||||
if(!isHex(s[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Wallet::isHexFamily(const std::string& s)
|
||||
{ // 64 characters, all legal hex
|
||||
if(s.size()!=64) return false;
|
||||
for(int i=0; i<64; i++)
|
||||
if(!isHex(s[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Wallet::privKeyToText(const uint256& privKey)
|
||||
{
|
||||
std::string ret("P");
|
||||
ret.append(privKey.GetHex());
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint256 Wallet::textToPrivKey(const std::string& privKey)
|
||||
{
|
||||
uint256 ret;
|
||||
if((privKey.length()==65) && (privKey[0]=='P'))
|
||||
ret.SetHex(privKey.c_str()+1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string LocalAccountFamily::getSQLFields()
|
||||
{
|
||||
return "(FamilyName,RootPubKey,Seq,Name,Comment)";
|
||||
return "(FamilyGenerator,Seq,Comment)";
|
||||
}
|
||||
|
||||
std::string LocalAccountFamily::getSQL() const
|
||||
{ // familyname(40), pubkey(66), seq, name, comment
|
||||
{ // familyname(40), seq, comment
|
||||
std::string ret("('");
|
||||
ret.append(mFamily.GetHex());
|
||||
ret+="','";
|
||||
ret.append(getPubGenHex());
|
||||
ret.append(mFamily.humanFamilyGenerator());
|
||||
ret.append("','");
|
||||
ret.append(boost::lexical_cast<std::string>(mLastSeq));
|
||||
ret.append("',");
|
||||
|
||||
std::string esc;
|
||||
theApp->getWalletDB()->getDB()->escape((const unsigned char *) mName.c_str(), mName.size(), esc);
|
||||
ret.append(esc);
|
||||
ret.append(",");
|
||||
theApp->getWalletDB()->getDB()->escape((const unsigned char *) mComment.c_str(), mComment.size(), esc);
|
||||
ret.append(esc);
|
||||
|
||||
@@ -302,71 +204,58 @@ LocalAccount::pointer LocalAccountFamily::get(int seq)
|
||||
|
||||
LocalAccount::pointer ret=boost::make_shared<LocalAccount>(shared_from_this(), seq);
|
||||
mAccounts.insert(std::make_pair(seq, ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint160 Wallet::findFamilySN(const std::string& shortName)
|
||||
{ // OPTIMIZEME
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
for(std::map<uint160, LocalAccountFamily::pointer>::iterator it=mFamilies.begin();
|
||||
it!=mFamilies.end(); ++it)
|
||||
NewcoinAddress Wallet::addFamily(const NewcoinAddress& familySeed, bool lock)
|
||||
{
|
||||
if(it->second->getShortName()==shortName)
|
||||
return it->first;
|
||||
}
|
||||
return 0;
|
||||
LocalAccountFamily::pointer fam(doPrivate(familySeed, true, !lock));
|
||||
|
||||
return fam ? fam->getFamily() : NewcoinAddress();
|
||||
}
|
||||
|
||||
uint160 Wallet::addFamily(const uint256& key, bool lock)
|
||||
// Create a family. Return the family public generator and the seed.
|
||||
NewcoinAddress Wallet::addRandomFamily(NewcoinAddress& familySeed)
|
||||
{
|
||||
LocalAccountFamily::pointer fam(doPrivate(key, true, !lock));
|
||||
if(!fam) return uint160();
|
||||
return fam->getFamily();
|
||||
}
|
||||
uint128 key;
|
||||
|
||||
uint160 Wallet::addRandomFamily(uint256& key)
|
||||
{
|
||||
RAND_bytes((unsigned char *) &key, sizeof(key));
|
||||
return addFamily(key, false);
|
||||
|
||||
familySeed.setFamilySeed(key);
|
||||
|
||||
return addFamily(familySeed, false);
|
||||
}
|
||||
|
||||
uint160 Wallet::addFamily(const std::string& payPhrase, bool lock)
|
||||
NewcoinAddress Wallet::addFamily(const std::string& payPhrase, bool lock)
|
||||
{
|
||||
return addFamily(CKey::PassPhraseToKey(payPhrase), lock);
|
||||
NewcoinAddress familySeed;
|
||||
|
||||
familySeed.setFamilySeed(CKey::PassPhraseToKey(payPhrase));
|
||||
|
||||
return addFamily(familySeed, lock);
|
||||
}
|
||||
|
||||
uint160 Wallet::addFamily(const std::string& pubKey)
|
||||
NewcoinAddress Wallet::addFamily(const NewcoinAddress& familyGenerator)
|
||||
{
|
||||
LocalAccountFamily::pointer fam(doPublic(pubKey, true, true));
|
||||
if(!fam) return uint160();
|
||||
return fam->getFamily();
|
||||
LocalAccountFamily::pointer fam(doPublic(familyGenerator, true, true));
|
||||
|
||||
return fam ? fam->getFamily() : NewcoinAddress();
|
||||
}
|
||||
|
||||
uint160 Wallet::findFamilyPK(const std::string& pubKey)
|
||||
NewcoinAddress Wallet::findFamilyPK(const NewcoinAddress& familyGenerator)
|
||||
{
|
||||
LocalAccountFamily::pointer fam(doPublic(pubKey, false, true));
|
||||
if(!fam) return uint160();
|
||||
return fam->getFamily();
|
||||
}
|
||||
LocalAccountFamily::pointer fam(doPublic(familyGenerator, false, true));
|
||||
|
||||
std::string LocalAccount::getShortName() const
|
||||
{
|
||||
std::string ret, cmt;
|
||||
|
||||
if(!theApp->getWallet().getFamilyInfo(mFamily->getFamily(), ret, cmt))
|
||||
ret=mFamily->getFamily().GetHex();
|
||||
ret.append(":");
|
||||
if(mName.empty())
|
||||
ret.append(boost::lexical_cast<std::string>(mAccountFSeq));
|
||||
else ret.append(mName);
|
||||
return ret;
|
||||
return fam ? fam->getFamily() : NewcoinAddress();
|
||||
}
|
||||
|
||||
std::string LocalAccount::getFullName() const
|
||||
{
|
||||
std::string ret(mFamily->getFamily().GetHex());
|
||||
std::string ret(mFamily->getFamily().humanFamilyGenerator());
|
||||
ret.append(":");
|
||||
ret.append(boost::lexical_cast<std::string>(mAccountFSeq));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -377,15 +266,14 @@ bool LocalAccount::isLocked() const
|
||||
|
||||
std::string LocalAccount::getFamilyName() const
|
||||
{
|
||||
return mFamily->getShortName();
|
||||
return mFamily->getFamily().humanFamilyGenerator();
|
||||
}
|
||||
|
||||
Json::Value LocalAccount::getJson() const
|
||||
{
|
||||
Json::Value ret(Json::objectValue);
|
||||
ret["Family"]=getFamilyName();
|
||||
ret["AccountID"]=NewcoinAddress(getAddress()).GetString();
|
||||
ret["ShortName"]=getShortName();
|
||||
ret["AccountID"]=getAddress().humanAccountID();
|
||||
ret["FullName"]=getFullName();
|
||||
ret["Issued"]=Json::Value(isIssued());
|
||||
ret["IsLocked"]=mFamily->isLocked();
|
||||
@@ -409,43 +297,49 @@ CKey::pointer LocalAccount::getPrivateKey()
|
||||
return mFamily->getPrivateKey(mAccountFSeq);
|
||||
}
|
||||
|
||||
void Wallet::getFamilies(std::vector<uint160>& familyIDs)
|
||||
void Wallet::getFamilies(std::vector<NewcoinAddress>& familyIDs)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
familyIDs.reserve(mFamilies.size());
|
||||
for(std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.begin(); fit!=mFamilies.end(); ++fit)
|
||||
for(std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.begin(); fit!=mFamilies.end(); ++fit)
|
||||
familyIDs.push_back(fit->first);
|
||||
}
|
||||
|
||||
bool Wallet::getFamilyInfo(const uint160& family, std::string& name, std::string& comment)
|
||||
// Look up a family in the wallet.
|
||||
bool Wallet::getFamilyInfo(const NewcoinAddress& family, std::string& comment)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit==mFamilies.end()) return false;
|
||||
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit==mFamilies.end())
|
||||
return false;
|
||||
|
||||
assert(fit->second->getFamily()==family);
|
||||
name=fit->second->getShortName();
|
||||
|
||||
comment=fit->second->getComment();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Wallet::getFullFamilyInfo(const uint160& family, std::string& name, std::string& comment,
|
||||
#if 0
|
||||
bool Wallet::getFullFamilyInfo(const NewcoinAddress& family, std::string& comment,
|
||||
std::string& pubGen, bool& isLocked)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit==mFamilies.end()) return false;
|
||||
assert(fit->second->getFamily()==family);
|
||||
name=fit->second->getShortName();
|
||||
comment=fit->second->getComment();
|
||||
pubGen=fit->second->getPubGenHex();
|
||||
isLocked=fit->second->isLocked();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
Json::Value Wallet::getFamilyJson(const uint160& family)
|
||||
Json::Value Wallet::getFamilyJson(const NewcoinAddress& family)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit==mFamilies.end()) return Json::Value(Json::nullValue);
|
||||
assert(fit->second->getFamily()==family);
|
||||
return fit->second->getJson();
|
||||
@@ -467,22 +361,21 @@ void Wallet::load()
|
||||
if(!db->startIterRows()) return;
|
||||
while(db->getNextRow())
|
||||
{
|
||||
std::string family, rootpub, name, comment;
|
||||
db->getStr("FamilyName", family);
|
||||
db->getStr("RootPubKey", rootpub);
|
||||
db->getStr("Name", name);
|
||||
std::string familyGenerator, comment;
|
||||
db->getStr("FamilyGenerator", familyGenerator);
|
||||
db->getStr("Comment", comment);
|
||||
int seq=db->getBigInt("Seq");
|
||||
|
||||
uint160 fb;
|
||||
fb.SetHex(family);
|
||||
NewcoinAddress family;
|
||||
|
||||
LocalAccountFamily::pointer f(doPublic(rootpub, true, false));
|
||||
family.setFamilyGenerator(familyGenerator);
|
||||
|
||||
LocalAccountFamily::pointer f(doPublic(family, true, false));
|
||||
if(f)
|
||||
{
|
||||
assert(f->getFamily()==fb);
|
||||
// XXX Compare could be better.
|
||||
assert(f->getFamily().getFamilyGenerator()==family.getFamilyGenerator());
|
||||
f->setSeq(seq);
|
||||
f->setName(name);
|
||||
f->setComment(comment);
|
||||
}
|
||||
else assert(false);
|
||||
@@ -490,35 +383,18 @@ void Wallet::load()
|
||||
db->endIterRows();
|
||||
}
|
||||
|
||||
std::string Wallet::getPubGenHex(const uint160& famBase)
|
||||
// YYY Perhaps this should take a comment.
|
||||
LocalAccount::pointer Wallet::getNewLocalAccount(const NewcoinAddress& family)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(famBase);
|
||||
if(fit==mFamilies.end()) return "";
|
||||
assert(fit->second->getFamily()==famBase);
|
||||
return fit->second->getPubGenHex();
|
||||
}
|
||||
|
||||
std::string Wallet::getShortName(const uint160& famBase)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(famBase);
|
||||
if(fit==mFamilies.end()) return "";
|
||||
assert(fit->second->getFamily()==famBase);
|
||||
return fit->second->getShortName();
|
||||
}
|
||||
|
||||
LocalAccount::pointer Wallet::getNewLocalAccount(const uint160& family)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit==mFamilies.end()) return LocalAccount::pointer();
|
||||
|
||||
uint32 seq=fit->second->getSeq();
|
||||
uint160 acct=fit->second->getAccount(seq, true);
|
||||
NewcoinAddress acct=fit->second->getAccount(seq, true);
|
||||
fit->second->setSeq(seq+1); // FIXME: writeout new seq
|
||||
|
||||
std::map<uint160, LocalAccount::pointer>::iterator ait=mAccounts.find(acct);
|
||||
std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait=mAccounts.find(acct);
|
||||
if(ait!=mAccounts.end()) return ait->second;
|
||||
|
||||
LocalAccount::pointer lac=boost::make_shared<LocalAccount>(fit->second, seq);
|
||||
@@ -526,17 +402,19 @@ LocalAccount::pointer Wallet::getNewLocalAccount(const uint160& family)
|
||||
|
||||
sl.unlock();
|
||||
lac->syncLedger();
|
||||
|
||||
return lac;
|
||||
}
|
||||
|
||||
LocalAccount::pointer Wallet::getLocalAccount(const uint160& family, int seq)
|
||||
LocalAccount::pointer Wallet::getLocalAccount(const NewcoinAddress& family, int seq)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit==mFamilies.end()) return LocalAccount::pointer();
|
||||
uint160 acct=fit->second->getAccount(seq, true);
|
||||
|
||||
std::map<uint160, LocalAccount::pointer>::iterator ait=mAccounts.find(acct);
|
||||
NewcoinAddress acct=fit->second->getAccount(seq, true);
|
||||
|
||||
std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait=mAccounts.find(acct);
|
||||
if(ait!=mAccounts.end()) return ait->second;
|
||||
|
||||
LocalAccount::pointer lac=boost::make_shared<LocalAccount>(fit->second, seq);
|
||||
@@ -544,13 +422,14 @@ LocalAccount::pointer Wallet::getLocalAccount(const uint160& family, int seq)
|
||||
|
||||
sl.unlock();
|
||||
lac->syncLedger();
|
||||
|
||||
return lac;
|
||||
}
|
||||
|
||||
LocalAccount::pointer Wallet::getLocalAccount(const uint160& acctID)
|
||||
LocalAccount::pointer Wallet::getLocalAccount(const NewcoinAddress& acctID)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccount::pointer>::iterator ait=mAccounts.find(acctID);
|
||||
std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait=mAccounts.find(acctID);
|
||||
if(ait==mAccounts.end()) return LocalAccount::pointer();
|
||||
return ait->second;
|
||||
}
|
||||
@@ -558,7 +437,7 @@ LocalAccount::pointer Wallet::getLocalAccount(const uint160& acctID)
|
||||
LocalAccount::pointer Wallet::findAccountForTransaction(uint64 amount)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
for(std::map<uint160, LocalAccount::pointer>::iterator it=mAccounts.begin(); it!=mAccounts.end(); ++it)
|
||||
for(std::map<NewcoinAddress, LocalAccount::pointer>::iterator it=mAccounts.begin(); it!=mAccounts.end(); ++it)
|
||||
if(!it->second->isLocked() && (it->second->getEffectiveBalance()>=amount) )
|
||||
return it->second;
|
||||
return LocalAccount::pointer();
|
||||
@@ -566,49 +445,64 @@ LocalAccount::pointer Wallet::findAccountForTransaction(uint64 amount)
|
||||
|
||||
LocalAccount::pointer Wallet::parseAccount(const std::string& specifier)
|
||||
{ // <family>:<seq> or <acct_id>
|
||||
|
||||
std::cerr << "Parse(" << specifier << ")" << std::endl;
|
||||
|
||||
size_t colon=specifier.find(':');
|
||||
if(colon == std::string::npos)
|
||||
{
|
||||
std::cerr << "nocolon" << std::endl;
|
||||
NewcoinAddress na(specifier);
|
||||
if(!na.IsValid()) return LocalAccount::pointer();
|
||||
return getLocalAccount(na.GetHash160());
|
||||
NewcoinAddress na;
|
||||
|
||||
if (na.setAccountID(specifier))
|
||||
{
|
||||
return getLocalAccount(na);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LocalAccount::pointer();
|
||||
}
|
||||
}
|
||||
|
||||
if (colon==0) return LocalAccount::pointer();
|
||||
|
||||
std::string family=specifier.substr(0, colon);
|
||||
std::string seq=specifier.substr(colon+1);
|
||||
|
||||
if(seq.empty()) return LocalAccount::pointer();
|
||||
|
||||
std::cerr << "family(" << family << "), seq(" << seq << ")" << std::endl;
|
||||
|
||||
uint160 f;
|
||||
if(isHexFamily(family))
|
||||
f.SetHex(family);
|
||||
else if(isHexPublicKey(family))
|
||||
f=findFamilyPK(family);
|
||||
else
|
||||
f=findFamilySN(family);
|
||||
if(!f) return LocalAccount::pointer();
|
||||
return getLocalAccount(f, boost::lexical_cast<int>(seq));
|
||||
NewcoinAddress familyParsed;
|
||||
NewcoinAddress familyFound;
|
||||
|
||||
if (familyParsed.setFamilyGenerator(family))
|
||||
{
|
||||
familyFound = findFamilyPK(familyParsed);
|
||||
}
|
||||
if (familyParsed.setFamilySeed(family))
|
||||
{
|
||||
// XXX Was private generator, should derive public generator.
|
||||
; // nothing
|
||||
}
|
||||
|
||||
uint160 Wallet::peekKey(const uint160& family, int seq)
|
||||
return familyFound.IsValid()
|
||||
? getLocalAccount(familyFound, boost::lexical_cast<int>(seq))
|
||||
: LocalAccount::pointer();
|
||||
}
|
||||
|
||||
NewcoinAddress Wallet::peekKey(const NewcoinAddress& family, int seq)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit==mFamilies.end()) return uint160();
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit==mFamilies.end()) return NewcoinAddress();
|
||||
|
||||
return fit->second->getAccount(seq, false);
|
||||
}
|
||||
|
||||
void Wallet::delFamily(const uint160& familyName)
|
||||
void Wallet::delFamily(const NewcoinAddress& familyName)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(familyName);
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(familyName);
|
||||
if(fit==mFamilies.end()) return;
|
||||
|
||||
std::map<int, LocalAccount::pointer>& acctMap=fit->second->getAcctMap();
|
||||
@@ -618,10 +512,13 @@ void Wallet::delFamily(const uint160& familyName)
|
||||
mFamilies.erase(familyName);
|
||||
}
|
||||
|
||||
LocalAccountFamily::pointer Wallet::doPublic(const std::string& pubKey, bool do_create, bool do_db)
|
||||
// --> pubKey: hex
|
||||
// --> do_create: Add to mFamilies
|
||||
// --> do_db: write out db
|
||||
LocalAccountFamily::pointer Wallet::doPublic(const NewcoinAddress& pubKey, bool do_create, bool do_db)
|
||||
{
|
||||
// Generate root key
|
||||
EC_KEY *pkey=CKey::GenerateRootPubKey(pubKey);
|
||||
EC_KEY *pkey=CKey::GenerateRootPubKey(pubKey.getFamilyGeneratorBN());
|
||||
if(!pkey)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -636,10 +533,12 @@ LocalAccountFamily::pointer Wallet::doPublic(const std::string& pubKey, bool do_
|
||||
unsigned char *begin=&rootPubKey[0];
|
||||
i2o_ECPublicKey(pkey, &begin);
|
||||
while(rootPubKey.size()<33) rootPubKey.push_back((unsigned char)0);
|
||||
uint160 family=NewcoinAddress(rootPubKey).GetHash160();
|
||||
|
||||
NewcoinAddress family;
|
||||
family.setFamilyGenerator(rootPubKey);
|
||||
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit!=mFamilies.end()) // already added
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
@@ -657,9 +556,10 @@ LocalAccountFamily::pointer Wallet::doPublic(const std::string& pubKey, bool do_
|
||||
fam=LocalAccountFamily::readFamily(family);
|
||||
if(fam) do_create=false;
|
||||
}
|
||||
|
||||
if(do_create)
|
||||
{
|
||||
fam=boost::make_shared<LocalAccountFamily>(family, EC_KEY_get0_group(pkey), EC_KEY_get0_public_key(pkey));
|
||||
fam=boost::make_shared<LocalAccountFamily>(family);
|
||||
mFamilies.insert(std::make_pair(family, fam));
|
||||
if(do_db) fam->write(true);
|
||||
}
|
||||
@@ -669,21 +569,14 @@ LocalAccountFamily::pointer Wallet::doPublic(const std::string& pubKey, bool do_
|
||||
return fam;
|
||||
}
|
||||
|
||||
LocalAccountFamily::pointer Wallet::doPrivate(const uint256& passPhrase, bool do_create, bool do_unlock)
|
||||
LocalAccountFamily::pointer Wallet::doPrivate(const NewcoinAddress& familySeed, bool do_create, bool do_unlock)
|
||||
{
|
||||
// Generate root key
|
||||
EC_KEY *base=CKey::GenerateRootDeterministicKey(passPhrase);
|
||||
|
||||
// Extract family name
|
||||
std::vector<unsigned char> rootPubKey(33, 0);
|
||||
unsigned char *begin=&rootPubKey[0];
|
||||
i2o_ECPublicKey(base, &begin);
|
||||
while(rootPubKey.size()<33) rootPubKey.push_back((unsigned char)0);
|
||||
uint160 family=NewcoinAddress(rootPubKey).GetHash160();
|
||||
NewcoinAddress family;
|
||||
family.setFamilyGenerator(familySeed);
|
||||
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
LocalAccountFamily::pointer fam;
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator it=mFamilies.find(family);
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator it=mFamilies.find(family);
|
||||
if(it==mFamilies.end())
|
||||
{ // family not found
|
||||
fam=LocalAccountFamily::readFamily(family);
|
||||
@@ -691,11 +584,9 @@ LocalAccountFamily::pointer Wallet::doPrivate(const uint256& passPhrase, bool do
|
||||
{
|
||||
if(!do_create)
|
||||
{
|
||||
EC_KEY_free(base);
|
||||
return LocalAccountFamily::pointer();
|
||||
}
|
||||
fam=boost::make_shared<LocalAccountFamily>(family,
|
||||
EC_KEY_get0_group(base), EC_KEY_get0_public_key(base));
|
||||
fam=boost::make_shared<LocalAccountFamily>(family);
|
||||
mFamilies.insert(std::make_pair(family, fam));
|
||||
fam->write(true);
|
||||
}
|
||||
@@ -703,17 +594,17 @@ LocalAccountFamily::pointer Wallet::doPrivate(const uint256& passPhrase, bool do
|
||||
else fam=it->second;
|
||||
|
||||
if(do_unlock && fam->isLocked())
|
||||
fam->unlock(EC_KEY_get0_private_key(base));
|
||||
fam->unlock(familySeed.getFamilyPrivateKey());
|
||||
|
||||
sl.unlock();
|
||||
EC_KEY_free(base);
|
||||
|
||||
return fam;
|
||||
}
|
||||
|
||||
bool Wallet::lock(const uint160& family)
|
||||
bool Wallet::lock(const NewcoinAddress& family)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
||||
if(fit==mFamilies.end()) return false;
|
||||
fit->second->lock();
|
||||
return true;
|
||||
@@ -722,13 +613,14 @@ bool Wallet::lock(const uint160& family)
|
||||
void Wallet::lock()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
for(std::map<uint160, LocalAccountFamily::pointer>::iterator fit=mFamilies.begin();
|
||||
for(std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.begin();
|
||||
fit!=mFamilies.end(); ++fit)
|
||||
fit->second->lock();
|
||||
}
|
||||
|
||||
bool Wallet::unitTest()
|
||||
{ // Create 100 keys for each of 1,000 families and ensure all keys match
|
||||
#if 0
|
||||
Wallet pub, priv;
|
||||
|
||||
uint256 privBase(time(NULL)^(getpid()<<16));
|
||||
@@ -736,12 +628,13 @@ bool Wallet::unitTest()
|
||||
|
||||
for(int i=0; i<1000; i++, privBase++)
|
||||
{
|
||||
uint160 fam=priv.addFamily(privBase, false);
|
||||
NewcoinAddress fam=priv.addFamily(privBase, false);
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Priv: " << privBase.GetHex() << " Fam: " << fam.GetHex() << std::endl;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
std::string pubGen=priv.getPubGenHex(fam);
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Pub: " << pubGen << std::endl;
|
||||
@@ -764,7 +657,7 @@ bool Wallet::unitTest()
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
for(int j=0; j<100; j++)
|
||||
{
|
||||
LocalAccount::pointer lpub=pub.getLocalAccount(fam, j);
|
||||
@@ -774,8 +667,8 @@ bool Wallet::unitTest()
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
uint160 lpuba=lpub->getAddress();
|
||||
uint160 lpriva=lpriv->getAddress();
|
||||
NewcoinAddress lpuba=lpub->getAddress();
|
||||
NewcoinAddress lpriva=lpriv->getAddress();
|
||||
#ifdef DEBUG
|
||||
// std::cerr << "pubA(" << j << "): " << lpuba.GetHex() << std::endl;
|
||||
// std::cerr << "prvA(" << j << "): " << lpriva.GetHex() << std::endl;
|
||||
@@ -793,6 +686,7 @@ bool Wallet::unitTest()
|
||||
priv.delFamily(fam);
|
||||
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -805,7 +699,7 @@ void Wallet::syncToLedger(bool force, Ledger* ledger)
|
||||
{ // check each transaction, see if it's in the ledger or allowed in the ledger
|
||||
// WRITEME
|
||||
}
|
||||
for(std::map<uint160, LocalAccount::pointer>::iterator ait=mAccounts.begin(); ait!=mAccounts.end(); ++ait)
|
||||
for(std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait=mAccounts.begin(); ait!=mAccounts.end(); ++ait)
|
||||
{ // check each account, see if our ledger balance matches
|
||||
LocalAccount::pointer& lac=ait->second;
|
||||
AccountState::pointer acs=ledger->getAccountState(ait->first);
|
||||
@@ -827,7 +721,7 @@ void Wallet::applyTransaction(Transaction::pointer txn)
|
||||
std::map<uint256, LocalTransaction::pointer>::iterator lti=mTransactions.find(txn->getID());
|
||||
if(lti!=mTransactions.end()) ltx=lti->second;
|
||||
|
||||
std::map<uint160, LocalAccount::pointer>::iterator lac=mAccounts.find(txn->getToAccount());
|
||||
std::map<NewcoinAddress, LocalAccount::pointer>::iterator lac=mAccounts.find(txn->getToAccount());
|
||||
if(lac!=mAccounts.end())
|
||||
{ // this is to a local account
|
||||
if(!ltx)
|
||||
@@ -897,10 +791,11 @@ bool Wallet::getTxJson(const uint256& txn, Json::Value& ret)
|
||||
std::map<uint256, LocalTransaction::pointer>::iterator it=mTransactions.find(txn);
|
||||
if(it==mTransactions.end()) return false;
|
||||
ret=it->second->getJson();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Wallet::getTxsJson(const uint160& account, Json::Value& ret)
|
||||
bool Wallet::getTxsJson(const NewcoinAddress& account, Json::Value& ret)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
for(std::map<uint256, LocalTransaction::pointer>::iterator it=mTransactions.begin();
|
||||
@@ -910,5 +805,7 @@ bool Wallet::getTxsJson(const uint160& account, Json::Value& ret)
|
||||
if(txn && ((account==txn->getFromAccount())||(account==txn->getToAccount())) )
|
||||
ret[it->first.GetHex()]=it->second->getJson();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
54
src/Wallet.h
54
src/Wallet.h
@@ -24,35 +24,32 @@ class Wallet
|
||||
protected:
|
||||
boost::recursive_mutex mLock;
|
||||
|
||||
std::map<uint160, LocalAccountFamily::pointer> mFamilies;
|
||||
std::map<uint160, LocalAccount::pointer> mAccounts;
|
||||
std::map<NewcoinAddress, LocalAccountFamily::pointer> mFamilies;
|
||||
std::map<NewcoinAddress, LocalAccount::pointer> mAccounts;
|
||||
std::map<uint256, LocalTransaction::pointer> mTransactions;
|
||||
|
||||
uint32 mLedger; // ledger we last synched to
|
||||
|
||||
LocalAccountFamily::pointer doPrivate(const uint256& passPhrase, bool do_create, bool do_unlock);
|
||||
LocalAccountFamily::pointer doPublic(const std::string& pubKey, bool do_create, bool do_db);
|
||||
LocalAccountFamily::pointer doPrivate(const NewcoinAddress& familySeed, bool do_create, bool do_unlock);
|
||||
LocalAccountFamily::pointer doPublic(const NewcoinAddress& pubKey, bool do_create, bool do_db);
|
||||
|
||||
void addFamily(const uint160& family, const std::string& pubKey, int seq,
|
||||
const std::string& name, const std::string& comment);
|
||||
// void addFamily(const NewcoinAddress& family, const std::string& pubKey, int seq, const std::string& name, const std::string& comment);
|
||||
|
||||
public:
|
||||
Wallet() : mLedger(0) { ; }
|
||||
|
||||
uint160 addFamily(const std::string& passPhrase, bool lock);
|
||||
uint160 addFamily(const uint256& passPhrase, bool lock);
|
||||
uint160 addFamily(const std::string& pubKey);
|
||||
uint160 addRandomFamily(uint256& privKey);
|
||||
NewcoinAddress addFamily(const std::string& passPhrase, bool lock);
|
||||
NewcoinAddress addFamily(const NewcoinAddress& familySeed, bool lock);
|
||||
NewcoinAddress addFamily(const NewcoinAddress& familyGenerator);
|
||||
NewcoinAddress addRandomFamily(NewcoinAddress& familySeed);
|
||||
|
||||
uint160 findFamilySN(const std::string& shortName);
|
||||
uint160 findFamilyPK(const std::string& pubKey);
|
||||
NewcoinAddress findFamilyPK(const NewcoinAddress& familyGenerator);
|
||||
|
||||
void delFamily(const uint160& familyName);
|
||||
void delFamily(const NewcoinAddress& familyName);
|
||||
|
||||
void getFamilies(std::vector<uint160>& familyIDs);
|
||||
void getFamilies(std::vector<NewcoinAddress>& familyIDs);
|
||||
|
||||
uint160 unlock(const uint256& passPhrase);
|
||||
bool lock(const uint160& familyName);
|
||||
bool lock(const NewcoinAddress& familyName);
|
||||
void lock();
|
||||
|
||||
void load();
|
||||
@@ -60,29 +57,20 @@ public:
|
||||
// must be a known local account
|
||||
LocalAccount::pointer parseAccount(const std::string& accountSpecifier);
|
||||
|
||||
LocalAccount::pointer getLocalAccount(const uint160& famBase, int seq);
|
||||
LocalAccount::pointer getLocalAccount(const uint160& acctID);
|
||||
LocalAccount::pointer getNewLocalAccount(const uint160& family);
|
||||
LocalAccount::pointer getLocalAccount(const NewcoinAddress& famBase, int seq);
|
||||
LocalAccount::pointer getLocalAccount(const NewcoinAddress& acctID);
|
||||
LocalAccount::pointer getNewLocalAccount(const NewcoinAddress& family);
|
||||
LocalAccount::pointer findAccountForTransaction(uint64 amount);
|
||||
uint160 peekKey(const uint160& family, int seq);
|
||||
std::string getPubGenHex(const uint160& famBase);
|
||||
std::string getShortName(const uint160& famBase);
|
||||
NewcoinAddress peekKey(const NewcoinAddress& family, int seq);
|
||||
|
||||
bool getFamilyInfo(const uint160& family, std::string& name, std::string& comment);
|
||||
bool getFullFamilyInfo(const uint160& family, std::string& name, std::string& comment,
|
||||
std::string& pubGen, bool& isLocked);
|
||||
bool getFamilyInfo(const NewcoinAddress& family, std::string& comment);
|
||||
// bool getFullFamilyInfo(const NewcoinAddress& family, std::string& comment, std::string& pubGen, bool& isLocked);
|
||||
|
||||
Json::Value getFamilyJson(const uint160& family);
|
||||
Json::Value getFamilyJson(const NewcoinAddress& family);
|
||||
bool getTxJson(const uint256& txid, Json::Value& value);
|
||||
bool getTxsJson(const uint160& acctid, Json::Value& value);
|
||||
bool getTxsJson(const NewcoinAddress& acctid, Json::Value& value);
|
||||
void addLocalTransactions(Json::Value&);
|
||||
|
||||
static bool isHexPrivateKey(const std::string&);
|
||||
static bool isHexPublicKey(const std::string&);
|
||||
static bool isHexFamily(const std::string&);
|
||||
static std::string privKeyToText(const uint256& privKey);
|
||||
static uint256 textToPrivKey(const std::string&);
|
||||
|
||||
void syncToLedger(bool force, Ledger* ledger);
|
||||
void applyTransaction(Transaction::pointer);
|
||||
|
||||
|
||||
19
src/base58.h
19
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<unsigned char> vchDataIn)
|
||||
{
|
||||
nVersion = nVersionIn;
|
||||
vchData = vchDataIn;
|
||||
}
|
||||
|
||||
void SetData(int nVersionIn, const void* pdata, size_t nSize)
|
||||
{
|
||||
nVersion = nVersionIn;
|
||||
@@ -195,14 +200,14 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
bool SetString(const char* psz)
|
||||
bool SetString(const char* psz, unsigned char version)
|
||||
{
|
||||
std::vector<unsigned char> vchTemp;
|
||||
DecodeBase58Check(psz, vchTemp);
|
||||
if (vchTemp.empty())
|
||||
if (vchTemp.empty() || vchTemp[0] != version)
|
||||
{
|
||||
vchData.clear();
|
||||
nVersion = 0;
|
||||
nVersion = 1;
|
||||
return false;
|
||||
}
|
||||
nVersion = vchTemp[0];
|
||||
@@ -213,9 +218,9 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetString(const std::string& str)
|
||||
bool SetString(const std::string& str, unsigned char version)
|
||||
{
|
||||
return SetString(str.c_str());
|
||||
return SetString(str.c_str(), version);
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
|
||||
25
src/key.h
25
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
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
#define for if (false) ; else for
|
||||
#endif
|
||||
@@ -33,6 +35,19 @@ protected:
|
||||
unsigned int pn[WIDTH];
|
||||
public:
|
||||
|
||||
BIGNUM *toBN() const
|
||||
{
|
||||
// Convert to big-endian
|
||||
unsigned char *be[WIDTH];
|
||||
unsigned char *bep;
|
||||
unsigned int *pnp = &pn[WIDTH];
|
||||
|
||||
for (int i=WIDTH; i--;)
|
||||
*bep++ = *--pnp;
|
||||
|
||||
return BN_bin2bn(be, WIDTH, NULL);
|
||||
}
|
||||
|
||||
bool isZero() const
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
@@ -415,22 +430,64 @@ public:
|
||||
}
|
||||
|
||||
|
||||
friend class uint128;
|
||||
friend class uint160;
|
||||
friend class uint256;
|
||||
friend inline int Testuint256AdHoc(std::vector<std::string> vArg);
|
||||
};
|
||||
|
||||
typedef base_uint<128> base_uint128;
|
||||
typedef base_uint<160> base_uint160;
|
||||
typedef base_uint<256> base_uint256;
|
||||
|
||||
|
||||
|
||||
//
|
||||
// uint160 and uint256 could be implemented as templates, but to keep
|
||||
// uint128, uint160, & uint256 could be implemented as templates, but to keep
|
||||
// compile errors and debugging cleaner, they're copy and pasted.
|
||||
//
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uint128
|
||||
//
|
||||
|
||||
class uint128 : public base_uint128
|
||||
{
|
||||
public:
|
||||
typedef base_uint128 basetype;
|
||||
|
||||
uint128()
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
uint128(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
}
|
||||
|
||||
uint128& operator=(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit uint128(const base_uint256 b) {
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
}
|
||||
|
||||
explicit uint128(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
if (vch.size() == sizeof(pn))
|
||||
memcpy(pn, &vch[0], sizeof(pn));
|
||||
else
|
||||
memset(pn, 0, sizeof(pn));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -543,11 +600,6 @@ inline const uint160 operator|(const uint160& a, const uint160& b) { return (b
|
||||
inline const uint160 operator+(const uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; }
|
||||
inline const uint160 operator-(const uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uint256
|
||||
@@ -792,3 +844,4 @@ inline int Testuint256AdHoc(std::vector<std::string> vArg)
|
||||
}
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
|
||||
Reference in New Issue
Block a user