mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 14:35:52 +00:00
New wallet system. Still missing unit tests, ledger synchronization,
and SQL code. This uses some of the 'magic' properties of elliptic curves to create related families of public and private keys. Wallet encryption is not needed because the private keys do not need to be stored.
This commit is contained in:
@@ -32,9 +32,14 @@ Application::Application()
|
|||||||
mRPCDoor=NULL;
|
mRPCDoor=NULL;
|
||||||
mDatabase=NULL;
|
mDatabase=NULL;
|
||||||
|
|
||||||
CKey::pointer account_key(new CKey(CKey::GetBaseFromString("This is my payphrase."), 0, false));
|
|
||||||
|
|
||||||
Ledger::pointer firstLedger(new Ledger(account_key->GetAddress().GetHash160(), 1000000));
|
uint160 rootFamily=mWallet.addFamily("This is my payphrase.", true);
|
||||||
|
LocalAccount::pointer rootAccount=mWallet.getLocalAccount(rootFamily, 0);
|
||||||
|
assert(!!rootAccount);
|
||||||
|
uint160 rootAddress=rootAccount->getAddress();
|
||||||
|
assert(!!rootAddress);
|
||||||
|
|
||||||
|
Ledger::pointer firstLedger(new Ledger(rootAddress, 1000000));
|
||||||
firstLedger->setClosed();
|
firstLedger->setClosed();
|
||||||
firstLedger->setAccepted();
|
firstLedger->setAccepted();
|
||||||
mMasterLedger.pushLedger(firstLedger);
|
mMasterLedger.pushLedger(firstLedger);
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
|
|
||||||
#include "Serializer.h"
|
#include "Serializer.h"
|
||||||
|
|
||||||
uint256 CKey::GetBaseFromString(const std::string& phrase)
|
uint256 CKey::PassPhraseToKey(const std::string& passPhrase)
|
||||||
{
|
{
|
||||||
Serializer s;
|
Serializer s;
|
||||||
s.addRaw((const void *) phrase.c_str(), phrase.length());
|
s.addRaw(passPhrase.c_str(), passPhrase.size());
|
||||||
uint256 base(s.getSHA512Half());
|
uint256 ret(s.getSHA512Half());
|
||||||
s.secureErase();
|
s.secureErase();
|
||||||
return base;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
EC_KEY* CKey::GenerateDeterministicKey(const uint256& base, uint32 n, bool private_key)
|
EC_KEY* CKey::GenerateRootDeterministicKey(const uint256& key)
|
||||||
{
|
{
|
||||||
BN_CTX* ctx=BN_CTX_new();
|
BN_CTX* ctx=BN_CTX_new();
|
||||||
if(!ctx) return NULL;
|
if(!ctx) return NULL;
|
||||||
@@ -44,9 +44,8 @@ EC_KEY* CKey::GenerateDeterministicKey(const uint256& base, uint32 n, bool priva
|
|||||||
int seq=0;
|
int seq=0;
|
||||||
do
|
do
|
||||||
{ // private key must be non-zero and less than the curve's order
|
{ // private key must be non-zero and less than the curve's order
|
||||||
Serializer s;
|
Serializer s(72);
|
||||||
s.add32(n);
|
s.add256(key);
|
||||||
s.add256(base);
|
|
||||||
s.add32(seq++);
|
s.add32(seq++);
|
||||||
uint256 root=s.getSHA512Half();
|
uint256 root=s.getSHA512Half();
|
||||||
s.secureErase();
|
s.secureErase();
|
||||||
@@ -62,7 +61,7 @@ EC_KEY* CKey::GenerateDeterministicKey(const uint256& base, uint32 n, bool priva
|
|||||||
|
|
||||||
BN_free(order);
|
BN_free(order);
|
||||||
|
|
||||||
if(private_key && !EC_KEY_set_private_key(pkey, privKey))
|
if(!EC_KEY_set_private_key(pkey, privKey))
|
||||||
{ // set the random point as the private key
|
{ // set the random point as the private key
|
||||||
assert(false);
|
assert(false);
|
||||||
EC_KEY_free(pkey);
|
EC_KEY_free(pkey);
|
||||||
@@ -98,8 +97,91 @@ EC_KEY* CKey::GenerateDeterministicKey(const uint256& base, uint32 n, bool priva
|
|||||||
return pkey;
|
return pkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 CKey::GetRandomBase(void)
|
static BIGNUM* makeHash(const uint160& family, int seq)
|
||||||
{
|
{
|
||||||
uint256 r;
|
Serializer s;
|
||||||
return (RAND_bytes((unsigned char *) &r, sizeof(uint256)) == 1) ? r : 0;
|
s.add160(family);
|
||||||
|
s.add32(seq);
|
||||||
|
uint256 root=s.getSHA512Half();
|
||||||
|
s.secureErase();
|
||||||
|
return BN_bin2bn((const unsigned char *) &root, sizeof(root), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
EC_KEY* CKey::GeneratePublicDeterministicKey(const uint160& family, EC_POINT* rootPubKey, int seq)
|
||||||
|
{ // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
|
||||||
|
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=EC_POINT_new(EC_KEY_get0_group(pkey));
|
||||||
|
if(newPoint==NULL)
|
||||||
|
{
|
||||||
|
EC_KEY_free(pkey);
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BIGNUM* hash=makeHash(family, seq);
|
||||||
|
if(hash==NULL)
|
||||||
|
{
|
||||||
|
EC_POINT_free(newPoint);
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
EC_KEY_free(pkey);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx);
|
||||||
|
BN_free(hash);
|
||||||
|
|
||||||
|
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, BIGNUM* rootPrivKey, int seq)
|
||||||
|
{ // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
BIGNUM* order=BN_new();
|
||||||
|
if(order==NULL)
|
||||||
|
{
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
EC_KEY_free(pkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx);
|
||||||
|
|
||||||
|
BIGNUM* privKey=makeHash(family, seq);
|
||||||
|
BN_mod_add(privKey, privKey, rootPrivKey, order, ctx);
|
||||||
|
BN_free(order);
|
||||||
|
|
||||||
|
EC_KEY_set_private_key(pkey, privKey);
|
||||||
|
|
||||||
|
EC_POINT* pubKey=EC_POINT_new(EC_KEY_get0_group(pkey));
|
||||||
|
EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx);
|
||||||
|
BN_free(privKey);
|
||||||
|
EC_KEY_set_public_key(pkey, pubKey);
|
||||||
|
|
||||||
|
EC_POINT_free(pubKey);
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
|
||||||
|
return pkey;
|
||||||
}
|
}
|
||||||
|
|||||||
13
Ledger.cpp
13
Ledger.cpp
@@ -260,17 +260,20 @@ Ledger::pointer Ledger::closeLedger(uint64 timeStamp)
|
|||||||
|
|
||||||
bool Ledger::unitTest()
|
bool Ledger::unitTest()
|
||||||
{
|
{
|
||||||
LocalAccount l1(true), l2(true);
|
uint160 la1=theApp->getWallet().addFamily(CKey::PassPhraseToKey("This is my payphrase!"), false);
|
||||||
assert(l1.peekPubKey());
|
uint160 la2=theApp->getWallet().addFamily(CKey::PassPhraseToKey("Another payphrase"), false);
|
||||||
|
|
||||||
|
LocalAccount::pointer l1=theApp->getWallet().getLocalAccount(la1, 0);
|
||||||
|
LocalAccount::pointer l2=theApp->getWallet().getLocalAccount(la2, 0);
|
||||||
|
|
||||||
|
assert(l1->getAddress()==la1);
|
||||||
|
|
||||||
uint160 la1(l1.getAddress()), la2(l2.getAddress());
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "Account1: " << la1.GetHex() << std::endl;
|
std::cerr << "Account1: " << la1.GetHex() << std::endl;
|
||||||
std::cerr << "Account2: " << la2.GetHex() << std::endl;
|
std::cerr << "Account2: " << la2.GetHex() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Ledger::pointer ledger(new Ledger(la1, 100000));
|
Ledger::pointer ledger(new Ledger(la1, 100000));
|
||||||
l1.mAmount=100000;
|
|
||||||
|
|
||||||
ledger=Ledger::pointer(new Ledger(*ledger, 0));
|
ledger=Ledger::pointer(new Ledger(*ledger, 0));
|
||||||
|
|
||||||
@@ -281,7 +284,7 @@ bool Ledger::unitTest()
|
|||||||
as=ledger->getAccountState(la2);
|
as=ledger->getAccountState(la2);
|
||||||
assert(!as);
|
assert(!as);
|
||||||
|
|
||||||
Transaction::pointer t(new Transaction(NEW, l1, l1.mSeqNum, l2.getAddress(), 2500, 0, 1));
|
Transaction::pointer t(new Transaction(NEW, l1, l1->getAcctSeq(), l2->getAddress(), 2500, 0, 1));
|
||||||
assert(!!t->getID());
|
assert(!!t->getID());
|
||||||
|
|
||||||
Ledger::TransResult tr=ledger->applyTransaction(t);
|
Ledger::TransResult tr=ledger->applyTransaction(t);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool NewcoinAddress::SetHash160(const uint160& hash160)
|
bool NewcoinAddress::SetHash160(const uint160& hash160)
|
||||||
{
|
{
|
||||||
SetData(51, &hash160, 20);
|
SetData(51, &hash160, 20);
|
||||||
@@ -25,7 +24,7 @@ NewcoinAddress::NewcoinAddress()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NewcoinAddress::NewcoinAddress(uint160& hash160In)
|
NewcoinAddress::NewcoinAddress(const uint160& hash160In)
|
||||||
{
|
{
|
||||||
SetHash160(hash160In);
|
SetHash160(hash160In);
|
||||||
}
|
}
|
||||||
@@ -53,3 +52,7 @@ uint160 NewcoinAddress::GetHash160() const
|
|||||||
return hash160;
|
return hash160;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string NewcoinAddress::GetString() const
|
||||||
|
{
|
||||||
|
return ToString();
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class NewcoinAddress : public CBase58Data
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NewcoinAddress();
|
NewcoinAddress();
|
||||||
NewcoinAddress(uint160& hash160In);
|
NewcoinAddress(const uint160& hash160In);
|
||||||
NewcoinAddress(const std::vector<unsigned char>& vchPubKey);
|
NewcoinAddress(const std::vector<unsigned char>& vchPubKey);
|
||||||
NewcoinAddress(const std::string& strAddress);
|
NewcoinAddress(const std::string& strAddress);
|
||||||
NewcoinAddress(const char* pszAddress);
|
NewcoinAddress(const char* pszAddress);
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ CREATE TABLE Ledgers ( -- closed/accepted ledgers
|
|||||||
CREATE INDEX SeqLedger ON Ledgers(LedgerSeq);
|
CREATE INDEX SeqLedger ON Ledgers(LedgerSeq);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE LedgerConfirmations (
|
CREATE TABLE LedgerConfirmations (
|
||||||
LedgerSeq BIGINT UNSIGNED,
|
LedgerSeq BIGINT UNSIGNED,
|
||||||
LedgerHash CHARACTER(64),
|
LedgerHash CHARACTER(64),
|
||||||
@@ -69,12 +68,22 @@ CREATE TABLE CommittedObjects ( -- used to synch nodes
|
|||||||
|
|
||||||
CREATE INDEX ObjectLocate ON CommittedObjects(LedgerIndex, ObjType);
|
CREATE INDEX ObjectLocate ON CommittedObjects(LedgerIndex, ObjType);
|
||||||
|
|
||||||
CREATE TABLE LocalAccounts ( -- wallet
|
CREATE TABLE LocalAcctFamilies ( -- a family of accounts that share a payphrase
|
||||||
|
FamilyName CHARACTER(40) PRIMARY KEY,
|
||||||
|
RootPubKey CHARACTER(66),
|
||||||
|
Seq BIGINT UNSIGNED, -- last one issued
|
||||||
|
Name TEXT,
|
||||||
|
Comment TEXT
|
||||||
|
)
|
||||||
|
|
||||||
|
CREATE TABLE LocalAccounts ( -- an individual account
|
||||||
ID CHARACTER(40) PRIMARY KEY,
|
ID CHARACTER(40) PRIMARY KEY,
|
||||||
|
DKID CHARACTER(40), -- root determinstic key
|
||||||
|
DKSeq BIGINT UNSIGNED, -- sequence number
|
||||||
Seq BIGINT UNSIGNED, -- last transaction seen/issued
|
Seq BIGINT UNSIGNED, -- last transaction seen/issued
|
||||||
Balance BIGINT UNSIGNED,
|
Balance BIGINT UNSIGNED,
|
||||||
LedgerSeq BIGINT UNSIGNED, -- ledger this balance is from
|
LedgerSeq BIGINT UNSIGNED, -- ledger this balance is from
|
||||||
KeyFormat CHARACTER(1), -- can be encrypted
|
|
||||||
PrivateKey BLOB,
|
|
||||||
Comment TEXT
|
Comment TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX AccountLocate ON LocalAccounts(DKID, DKSeq);
|
||||||
|
|||||||
@@ -14,14 +14,13 @@ Transaction::Transaction() : mTransactionID(0), mAccountFrom(0), mAccountTo(0),
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::Transaction(TransStatus status, LocalAccount& fromLocalAccount, uint32 fromSeq,
|
Transaction::Transaction(TransStatus status, LocalAccount::pointer fromLocalAccount, uint32 fromSeq,
|
||||||
const uint160& toAccount, uint64 amount, uint32 ident, uint32 ledger) :
|
const uint160& toAccount, uint64 amount, uint32 ident, uint32 ledger) :
|
||||||
mAccountTo(toAccount), mAmount(amount), mFromAccountSeq(fromSeq), mSourceLedger(ledger),
|
mAccountTo(toAccount), mAmount(amount), mFromAccountSeq(fromSeq), mSourceLedger(ledger),
|
||||||
mIdent(ident), mInLedger(0), mStatus(NEW)
|
mIdent(ident), mInLedger(0), mStatus(NEW)
|
||||||
{
|
{
|
||||||
assert(fromLocalAccount.mAmount>=amount);
|
mAccountFrom=fromLocalAccount->getAddress();
|
||||||
mAccountFrom=fromLocalAccount.getAddress();
|
mFromPubKey=fromLocalAccount->getPublicKey();
|
||||||
mFromPubKey=fromLocalAccount.peekPubKey();
|
|
||||||
assert(mFromPubKey);
|
assert(mFromPubKey);
|
||||||
updateFee();
|
updateFee();
|
||||||
sign(fromLocalAccount);
|
sign(fromLocalAccount);
|
||||||
@@ -51,21 +50,24 @@ Transaction::Transaction(const std::vector<unsigned char> &t, bool validate) : m
|
|||||||
mStatus=NEW;
|
mStatus=NEW;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Transaction::sign(LocalAccount& fromLocalAccount)
|
bool Transaction::sign(LocalAccount::pointer fromLocalAccount)
|
||||||
{
|
{
|
||||||
|
CKey::pointer privateKey=fromLocalAccount->getPrivateKey();
|
||||||
|
if(!privateKey) return false;
|
||||||
|
|
||||||
if( (mAmount==0) || (mSourceLedger==0) || (mAccountTo==0) )
|
if( (mAmount==0) || (mSourceLedger==0) || (mAccountTo==0) )
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(mAccountFrom!=fromLocalAccount.mAddress.GetHash160())
|
if(mAccountFrom!=fromLocalAccount->getAddress())
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Serializer::pointer signBuf=getRaw(true);
|
Serializer::pointer signBuf=getRaw(true);
|
||||||
assert(signBuf->getLength()==73+4);
|
assert(signBuf->getLength()==73+4);
|
||||||
if(!signBuf->makeSignature(mSignature, fromLocalAccount.peekPrivKey()))
|
if(!signBuf->makeSignature(mSignature, *privateKey))
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "newcoin.pb.h"
|
#include "newcoin.pb.h"
|
||||||
#include "Hanko.h"
|
#include "Hanko.h"
|
||||||
#include "Serializer.h"
|
#include "Serializer.h"
|
||||||
|
#include "Wallet.h"
|
||||||
#include "SHAMap.h"
|
#include "SHAMap.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -29,9 +30,6 @@ enum TransStatus
|
|||||||
INCOMPLETE =8 // needs more signatures
|
INCOMPLETE =8 // needs more signatures
|
||||||
};
|
};
|
||||||
|
|
||||||
class Account;
|
|
||||||
class LocalAccount;
|
|
||||||
|
|
||||||
class Transaction : public boost::enable_shared_from_this<Transaction>
|
class Transaction : public boost::enable_shared_from_this<Transaction>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -54,10 +52,10 @@ private:
|
|||||||
public:
|
public:
|
||||||
Transaction();
|
Transaction();
|
||||||
Transaction(const std::vector<unsigned char>& rawTransaction, bool validate);
|
Transaction(const std::vector<unsigned char>& rawTransaction, bool validate);
|
||||||
Transaction(TransStatus Status, LocalAccount& fromLocal, uint32 fromSeq, const uint160& to, uint64 amount,
|
Transaction(TransStatus Status, LocalAccount::pointer fromLocal, uint32 fromSeq, const uint160& to, uint64 amount,
|
||||||
uint32 ident, uint32 ledger);
|
uint32 ident, uint32 ledger);
|
||||||
|
|
||||||
bool sign(LocalAccount& fromLocalAccount);
|
bool sign(LocalAccount::pointer fromLocalAccount);
|
||||||
bool checkSign() const;
|
bool checkSign() const;
|
||||||
void updateID();
|
void updateID();
|
||||||
void updateFee();
|
void updateFee();
|
||||||
|
|||||||
357
Wallet.cpp
357
Wallet.cpp
@@ -1,185 +1,224 @@
|
|||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "boost/lexical_cast.hpp"
|
||||||
|
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
#include "NewcoinAddress.h"
|
#include "NewcoinAddress.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include <string>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
LocalAccount::LocalAccount(bool) : mPublicKey(new CKey()), mAmount(0), mSeqNum(0)
|
|
||||||
|
LocalAccountEntry::LocalAccountEntry(const uint160& accountFamily, int accountSeq, EC_POINT* rootPubKey) :
|
||||||
|
mAccountFamily(accountFamily), mAccountSeq(accountSeq),
|
||||||
|
mPublicKey(new CKey(accountFamily, rootPubKey, accountSeq)),
|
||||||
|
mBalance(0), mLedgerSeq(0), mTxnSeq(0)
|
||||||
{
|
{
|
||||||
mPrivateKey.MakeNewKey();
|
mAcctID=mPublicKey->GetAddress().GetHash160();
|
||||||
mPublicKey->SetPubKey(mPrivateKey.GetPubKey());
|
mPublicKey=theApp->getPubKeyCache().store(mAcctID, mPublicKey);
|
||||||
acctID=Hash160(mPublicKey->GetPubKey());
|
|
||||||
mPublicKey=theApp->getPubKeyCache().store(acctID, mPublicKey);
|
|
||||||
assert(mPublicKey);
|
|
||||||
mAddress.SetHash160(acctID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Wallet::Wallet()
|
void LocalAccountEntry::unlock(BIGNUM* rootPrivKey)
|
||||||
{
|
{
|
||||||
|
if((mPrivateKey==NULL) && (rootPrivKey!=NULL))
|
||||||
|
mPrivateKey=CKey::pointer(new CKey(mAccountFamily, rootPrivKey, mAccountSeq));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string LocalAccountEntry::getAccountName() const
|
||||||
|
{
|
||||||
|
return mPublicKey->GetAddress().GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LocalAccountEntry::getLocalAccountName() const
|
||||||
|
{
|
||||||
|
return NewcoinAddress(mAccountFamily).GetString() + ":" + boost::lexical_cast<std::string>(mAccountSeq);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalAccountFamily::LocalAccountFamily(const uint160& family, EC_POINT* pubKey) :
|
||||||
|
mFamily(family), rootPubKey(pubKey), rootPrivateKey(NULL)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
LocalAccountFamily::~LocalAccountFamily()
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
if(rootPubKey!=NULL) EC_POINT_free(rootPubKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint160 LocalAccountFamily::getAccount(int seq)
|
||||||
|
{
|
||||||
|
std::map<int, LocalAccountEntry::pointer>::iterator ait=mAccounts.find(seq);
|
||||||
|
if(ait!=mAccounts.end()) return ait->second->getAccountID();
|
||||||
|
|
||||||
|
LocalAccountEntry::pointer lae(new LocalAccountEntry(mFamily, seq, rootPubKey));
|
||||||
|
mAccounts.insert(std::make_pair(seq, lae));
|
||||||
|
|
||||||
|
return lae->getAccountID();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalAccountFamily::unlock(BIGNUM* privateKey)
|
||||||
|
{
|
||||||
|
if(rootPrivateKey!=NULL) BN_free(rootPrivateKey);
|
||||||
|
rootPrivateKey=privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalAccountFamily::lock()
|
||||||
|
{
|
||||||
|
if(rootPrivateKey!=NULL)
|
||||||
|
{
|
||||||
|
BN_free(rootPrivateKey);
|
||||||
|
rootPrivateKey=NULL;
|
||||||
|
for(std::map<int, LocalAccountEntry::pointer>::iterator it=mAccounts.begin(); it!=mAccounts.end(); ++it)
|
||||||
|
it->second->lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalAccountEntry::pointer LocalAccountFamily::get(int seq)
|
||||||
|
{
|
||||||
|
std::map<int, LocalAccountEntry::pointer>::iterator act=mAccounts.find(seq);
|
||||||
|
if(act!=mAccounts.end()) return act->second;
|
||||||
|
|
||||||
|
LocalAccountEntry::pointer ret(new LocalAccountEntry(mFamily, seq, rootPubKey));
|
||||||
|
mAccounts.insert(std::make_pair(seq, ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint160 Wallet::addFamily(const std::string& payPhrase, bool lock)
|
||||||
|
{
|
||||||
|
return doPrivate(CKey::PassPhraseToKey(payPhrase), true, !lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Wallet::addFamily(const uint160& familyName, const std::string& pubKey)
|
||||||
|
{
|
||||||
|
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=families.find(familyName);
|
||||||
|
if(fit!=families.end()) // already added
|
||||||
|
return true;
|
||||||
|
|
||||||
|
EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||||
|
if(!grp) return false;
|
||||||
|
|
||||||
|
BIGNUM* pbn=NULL;
|
||||||
|
BN_hex2bn(&pbn, pubKey.c_str());
|
||||||
|
if(!pbn)
|
||||||
|
{
|
||||||
|
EC_GROUP_free(grp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EC_POINT* rootPub=EC_POINT_bn2point(grp, pbn, NULL, NULL);
|
||||||
|
EC_GROUP_free(grp);
|
||||||
|
BN_free(pbn);
|
||||||
|
if(!rootPub)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalAccountFamily::pointer fam(new LocalAccountFamily(familyName, rootPub));
|
||||||
|
families.insert(std::make_pair(familyName, fam));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Wallet::getPubKey(const uint160& famBase)
|
||||||
|
{
|
||||||
|
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=families.find(famBase);
|
||||||
|
if(fit==families.end()) return "";
|
||||||
|
|
||||||
|
EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||||
|
if(!grp) return "";
|
||||||
|
|
||||||
|
BIGNUM* pubBase=EC_POINT_point2bn(grp, fit->second->peekPubKey(), POINT_CONVERSION_COMPRESSED, NULL, NULL);
|
||||||
|
EC_GROUP_free(grp);
|
||||||
|
if(!pubBase) return "";
|
||||||
|
char *hex=BN_bn2hex(pubBase);
|
||||||
|
BN_free(pubBase);
|
||||||
|
if(!hex) return "";
|
||||||
|
std::string ret(hex);
|
||||||
|
OPENSSL_free(hex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint160 LocalAccount::getAddress() const
|
||||||
|
{
|
||||||
|
LocalAccountEntry::pointer la(mFamily->get(mSeq));
|
||||||
|
if(!la) return uint160();
|
||||||
|
return la->getAccountID();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 LocalAccount::getAcctSeq() const
|
||||||
|
{
|
||||||
|
LocalAccountEntry::pointer la(mFamily->get(mSeq));
|
||||||
|
if(!la) return 0;
|
||||||
|
return la->getAccountSeq();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 LocalAccount::getBalance() const
|
||||||
|
{
|
||||||
|
LocalAccountEntry::pointer la(mFamily->get(mSeq));
|
||||||
|
if(!la) return 0;
|
||||||
|
return la->getBalance();
|
||||||
|
}
|
||||||
|
|
||||||
|
CKey::pointer LocalAccount::getPublicKey()
|
||||||
|
{
|
||||||
|
LocalAccountEntry::pointer la(mFamily->get(mSeq));
|
||||||
|
if(!la) return CKey::pointer();
|
||||||
|
return la->getPubKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
CKey::pointer LocalAccount::getPrivateKey()
|
||||||
|
{
|
||||||
|
LocalAccountEntry::pointer la(mFamily->get(mSeq));
|
||||||
|
if(!la) return CKey::pointer();
|
||||||
|
return la->getPrivKey();
|
||||||
|
}
|
||||||
|
|
||||||
void Wallet::load()
|
void Wallet::load()
|
||||||
{
|
{
|
||||||
// WRITEME
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
LocalAccount::pointer Wallet::getLocalAccount(const uint160& family, int seq)
|
||||||
|
|
||||||
int64 Wallet::getBalance()
|
|
||||||
{
|
{
|
||||||
int64 total = 0;
|
std::map<uint160, LocalAccountFamily::pointer>::iterator fit=families.find(family);
|
||||||
|
if(fit==families.end()) return LocalAccount::pointer();
|
||||||
|
uint160 acct=fit->second->getAccount(seq);
|
||||||
|
|
||||||
LedgerMaster& ledgerMaster=theApp->getLedgerMaster();
|
std::map<uint160, LocalAccount::pointer>::iterator ait=accounts.find(acct);
|
||||||
|
if(ait!=accounts.end()) return ait->second;
|
||||||
|
|
||||||
BOOST_FOREACH(Account& account, mYourAccounts)
|
LocalAccount::pointer lac(new LocalAccount(fit->second, seq));
|
||||||
{
|
accounts.insert(std::make_pair(acct, lac));
|
||||||
total += ledgerMaster.getAmountHeld(account.mAddress);
|
return lac;
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::refreshAccounts()
|
uint160 Wallet::doPrivate(const uint256& passPhrase, bool create, bool unlock)
|
||||||
{
|
{
|
||||||
LedgerMaster& ledgerMaster=theApp->getLedgerMaster();
|
// Generate root key
|
||||||
|
EC_KEY *base=CKey::GenerateRootDeterministicKey(passPhrase);
|
||||||
|
|
||||||
BOOST_FOREACH(Account& account, mYourAccounts)
|
// 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();
|
||||||
|
|
||||||
|
LocalAccountFamily::pointer fam;
|
||||||
|
std::map<uint160, LocalAccountFamily::pointer>::iterator it=families.find(family);
|
||||||
|
if(it==families.end())
|
||||||
|
{ // family not found
|
||||||
|
if(!create)
|
||||||
{
|
{
|
||||||
Ledger::Account* ledgerAccount=ledgerMaster.getAccount(account.mAddress);
|
EC_KEY_free(base);
|
||||||
if(ledgerAccount)
|
return family;
|
||||||
{
|
|
||||||
account.mAmount= ledgerAccount->first;
|
|
||||||
account.mSeqNum= ledgerAccount->second;
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
account.mAmount=0;
|
|
||||||
account.mSeqNum=0;
|
|
||||||
}
|
}
|
||||||
|
fam=LocalAccountFamily::pointer(new LocalAccountFamily(family,
|
||||||
|
EC_POINT_dup(EC_KEY_get0_public_key(base), EC_KEY_get0_group(base))));
|
||||||
|
families[family]=fam;
|
||||||
}
|
}
|
||||||
|
else fam=it->second;
|
||||||
|
|
||||||
|
if(unlock && fam->isLocked())
|
||||||
|
fam->unlock(BN_dup(EC_KEY_get0_private_key(base)));
|
||||||
|
|
||||||
|
EC_KEY_free(base);
|
||||||
|
return family;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::transactionChanged(TransactionPtr trans)
|
|
||||||
{
|
|
||||||
|
|
||||||
BOOST_FOREACH(Account& account, mYourAccounts)
|
|
||||||
{
|
|
||||||
if( account.mAddress == protobufTo160(trans->from()) ||
|
|
||||||
account.mAddress == protobufTo160(trans->dest()) )
|
|
||||||
{
|
|
||||||
Ledger::Account* ledgerAccount=theApp->getLedgerMaster().getAccount(account.mAddress);
|
|
||||||
if(ledgerAccount)
|
|
||||||
{
|
|
||||||
account.mAmount= ledgerAccount->first;
|
|
||||||
account.mSeqNum= ledgerAccount->second;
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
account.mAmount=0;
|
|
||||||
account.mSeqNum=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Wallet::Account* Wallet::consolidateAccountOfSize(int64 amount)
|
|
||||||
{
|
|
||||||
int64 total=0;
|
|
||||||
BOOST_FOREACH(Account& account, mYourAccounts)
|
|
||||||
{
|
|
||||||
if(account.mAmount>=amount) return(&account);
|
|
||||||
total += account.mAmount;
|
|
||||||
}
|
|
||||||
if(total<amount) return(NULL);
|
|
||||||
|
|
||||||
Account* firstAccount=NULL;
|
|
||||||
uint160* firstAddr=NULL;
|
|
||||||
total=0;
|
|
||||||
BOOST_FOREACH(Account& account, mYourAccounts)
|
|
||||||
{
|
|
||||||
total += account.mAmount;
|
|
||||||
if(firstAccount)
|
|
||||||
{
|
|
||||||
TransactionPtr trans=createTransaction(account,firstAccount->mAddress,account.mAmount);
|
|
||||||
commitTransaction(trans);
|
|
||||||
}else firstAccount=&account;
|
|
||||||
|
|
||||||
if(total>=amount) return(firstAccount);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(0);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
string Wallet::sendMoneyToAddress(uint160& destAddress, int64 amount)
|
|
||||||
{
|
|
||||||
// we may have to bundle up money in order to send this amount
|
|
||||||
Account* fromAccount=consolidateAccountOfSize(amount);
|
|
||||||
if(fromAccount)
|
|
||||||
{
|
|
||||||
TransactionPtr trans=createTransaction(*fromAccount,destAddress,amount);
|
|
||||||
if(trans)
|
|
||||||
{
|
|
||||||
if(!commitTransaction(trans))
|
|
||||||
return("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
|
||||||
|
|
||||||
}
|
|
||||||
}else return("Insufficient funds");
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
TransactionPtr Wallet::createTransaction(Account& fromAccount, uint160& destAddr, int64 amount)
|
|
||||||
{
|
|
||||||
TransactionPtr trans(new newcoin::Transaction());
|
|
||||||
trans->set_amount(amount);
|
|
||||||
trans->set_seqnum(fromAccount.mSeqNum);
|
|
||||||
trans->set_from(fromAccount.mAddress.begin(), fromAccount.mAddress.GetSerializeSize());
|
|
||||||
trans->set_dest(destAddr.begin(),destAddr.GetSerializeSize());
|
|
||||||
trans->set_ledgerindex(theApp->getLedgerMaster().getCurrentLedgerIndex());
|
|
||||||
// TODO: trans->set_pubkey(fromAccount.mPublicKey);
|
|
||||||
fromAccount.signTransaction(trans);
|
|
||||||
|
|
||||||
return(trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Wallet::Account::signTransaction(TransactionPtr trans)
|
|
||||||
{
|
|
||||||
/* TODO:
|
|
||||||
uint256 hash = Transaction::calcHash(trans);
|
|
||||||
|
|
||||||
CKey key;
|
|
||||||
if(!GetKey(input.from(), key))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(hash != 0)
|
|
||||||
{
|
|
||||||
vector<unsigned char> vchSig;
|
|
||||||
if(!key.Sign(hash, retSig))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Wallet::commitTransaction(TransactionPtr trans)
|
|
||||||
{
|
|
||||||
if(trans)
|
|
||||||
{
|
|
||||||
if(theApp->getLedgerMaster().addTransaction(trans))
|
|
||||||
{
|
|
||||||
ConnectionPool& pool=theApp->getConnectionPool();
|
|
||||||
PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(new newcoin::Transaction(*(trans.get()))),newcoin::TRANSACTION));
|
|
||||||
pool.relayMessage(NULL,packet);
|
|
||||||
|
|
||||||
}else cout << "Problem adding the transaction to your local ledger" << endl;
|
|
||||||
}
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|||||||
154
Wallet.h
154
Wallet.h
@@ -1,64 +1,146 @@
|
|||||||
#ifndef __WALLET__
|
#ifndef __WALLET__
|
||||||
#define __WALLET__
|
#define __WALLET__
|
||||||
|
|
||||||
#include "keystore.h"
|
|
||||||
#include "Serializer.h"
|
|
||||||
#include "Transaction.h"
|
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class NewcoinAddress;
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include "openssl/ec.h"
|
||||||
|
|
||||||
|
#include "uint256.h"
|
||||||
|
#include "Serializer.h"
|
||||||
|
|
||||||
|
class LocalAccountEntry
|
||||||
|
{ // tracks keys for local accounts
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<LocalAccountEntry> pointer;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// family informaiton
|
||||||
|
uint160 mAccountFamily;
|
||||||
|
int mAccountSeq;
|
||||||
|
|
||||||
|
// core account information
|
||||||
|
CKey::pointer mPublicKey;
|
||||||
|
CKey::pointer mPrivateKey;
|
||||||
|
uint160 mAcctID;
|
||||||
|
|
||||||
|
// local usage tracking
|
||||||
|
uint64 mBalance; // The balance, last we checked/updated
|
||||||
|
uint32 mLedgerSeq; // The ledger seq when we updated the balance
|
||||||
|
uint32 mTxnSeq; // The sequence number of the next transaction
|
||||||
|
|
||||||
|
public:
|
||||||
|
LocalAccountEntry(const uint160& accountFamily, int accountSeq, EC_POINT* rootPubKey);
|
||||||
|
|
||||||
|
void unlock(BIGNUM* rootPrivKey);
|
||||||
|
void lock() { mPrivateKey=CKey::pointer(); }
|
||||||
|
|
||||||
|
void write();
|
||||||
|
void read();
|
||||||
|
|
||||||
|
const uint160& getAccountID() const { return mAcctID; }
|
||||||
|
int getAccountSeq() const { return mAccountSeq; }
|
||||||
|
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
|
||||||
|
|
||||||
|
CKey::pointer getPubKey() { return mPublicKey; }
|
||||||
|
CKey::pointer getPrivKey() { return mPrivateKey; }
|
||||||
|
|
||||||
|
void update(uint64 balance, uint32 seq);
|
||||||
|
uint32 getTxnSeq() const { return mTxnSeq; }
|
||||||
|
uint32 incTxnSeq() { return mTxnSeq++; }
|
||||||
|
|
||||||
|
uint64 getBalance() const { return mBalance; }
|
||||||
|
void credit(uint64 amount) { mBalance+=amount; }
|
||||||
|
void debit(uint64 amount) { assert(mBalance>=amount); mBalance-=amount; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class LocalAccountFamily
|
||||||
|
{ // tracks families of local accounts
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<LocalAccountFamily> pointer;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::map<int, LocalAccountEntry::pointer> mAccounts;
|
||||||
|
|
||||||
|
uint160 mFamily; // the name for this account family
|
||||||
|
EC_POINT* rootPubKey;
|
||||||
|
|
||||||
|
BIGNUM* rootPrivateKey;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
LocalAccountFamily(const uint160& family, EC_POINT* pubKey);
|
||||||
|
~LocalAccountFamily();
|
||||||
|
|
||||||
|
const uint160& getFamily() { return mFamily; }
|
||||||
|
bool isLocked() const { return rootPrivateKey==NULL; }
|
||||||
|
void unlock(BIGNUM* privateKey);
|
||||||
|
void lock();
|
||||||
|
|
||||||
|
const EC_POINT* peekPubKey() const { return rootPubKey; }
|
||||||
|
|
||||||
|
LocalAccountEntry::pointer get(int seq);
|
||||||
|
uint160 getAccount(int seq);
|
||||||
|
|
||||||
|
std::string getPubName() const; // The text name of the public key
|
||||||
|
std::string getShortName() const; // The text name for the family
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Keeps track of all the public/private keys you have created
|
|
||||||
*/
|
|
||||||
class LocalAccount
|
class LocalAccount
|
||||||
{
|
{ // tracks a single local account
|
||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<LocalAccount> pointer;
|
typedef boost::shared_ptr<LocalAccount> pointer;
|
||||||
|
|
||||||
//CKey mKey;
|
protected:
|
||||||
//std::string mHumanAddress;
|
LocalAccountFamily::pointer mFamily;
|
||||||
NewcoinAddress mAddress;
|
int mSeq;
|
||||||
CKey::pointer mPublicKey;
|
|
||||||
CKey mPrivateKey;
|
|
||||||
uint160 acctID;
|
|
||||||
int64 mAmount;
|
|
||||||
uint32 mSeqNum;
|
|
||||||
|
|
||||||
LocalAccount(bool); // create a new local acount
|
|
||||||
|
public:
|
||||||
|
LocalAccount(LocalAccountFamily::pointer fam, int seq) : mFamily(fam), mSeq(seq) { ; }
|
||||||
|
uint160 getAddress() const;
|
||||||
|
bool isLocked() const;
|
||||||
|
|
||||||
bool signRaw(Serializer::pointer);
|
bool signRaw(Serializer::pointer);
|
||||||
bool signRaw(Serializer::pointer, std::vector<unsigned char>& signature);
|
bool signRaw(Serializer::pointer, std::vector<unsigned char>& signature);
|
||||||
bool checkSignRaw(Serializer::pointer, int signaturePosition=-1, int signedData=-1);
|
bool checkSignRaw(Serializer::pointer data, std::vector<unsigned char>& signature);
|
||||||
CKey& peekPrivKey() { return mPrivateKey; }
|
|
||||||
CKey::pointer peekPubKey() { return mPublicKey; }
|
|
||||||
|
|
||||||
uint160 getAddress() const { return mAddress.GetHash160(); }
|
uint32 getAcctSeq() const;
|
||||||
|
uint64 getBalance() const;
|
||||||
|
void incAcctSeq(uint32 transAcctSeq);
|
||||||
|
|
||||||
|
CKey::pointer getPublicKey();
|
||||||
|
CKey::pointer getPrivateKey();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Wallet : public CBasicKeyStore
|
class Wallet
|
||||||
{
|
{
|
||||||
std::map<uint160, LocalAccount::pointer> mYourAccounts;
|
protected:
|
||||||
|
std::map<uint160, LocalAccountFamily::pointer> families;
|
||||||
|
std::map<uint160, LocalAccount::pointer> accounts;
|
||||||
|
|
||||||
Transaction::pointer createTransaction(LocalAccount& fromAccount, const uint160& destAddr, uint64 amount);
|
uint160 doPrivate(const uint256& passPhrase, bool create, bool unlock);
|
||||||
bool commitTransaction(Transaction::pointer trans);
|
|
||||||
|
|
||||||
LocalAccount* consolidateAccountOfSize(int64 amount);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Wallet();
|
Wallet() { ; }
|
||||||
void refreshAccounts();
|
|
||||||
void load();
|
|
||||||
|
|
||||||
uint64 getBalance();
|
uint160 addFamily(const std::string& passPhrase, bool lock);
|
||||||
|
uint160 addFamily(const uint256& passPhrase, bool lock) { return doPrivate(passPhrase, true, !lock); }
|
||||||
|
bool addFamily(const uint160& familyName, const std::string& pubKey);
|
||||||
|
|
||||||
// returns some human error str?
|
uint160 unlock(const uint256& passPhrase) { return doPrivate(passPhrase, false, true); }
|
||||||
std::string sendMoneyToAddress(const uint160& destAddress, uint64 amount);
|
|
||||||
|
|
||||||
// you may need to update your balances
|
bool lock(const uint160& familyName);
|
||||||
void transactionChanged(Transaction::pointer trans);
|
|
||||||
|
|
||||||
|
void load(void);
|
||||||
|
|
||||||
|
LocalAccount::pointer getLocalAccount(const uint160& famBase, int seq);
|
||||||
|
LocalAccount::pointer getLocalAccount(const uint160& acctID);
|
||||||
|
std::string getPubKey(const uint160& famBase);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
22
key.h
22
key.h
@@ -86,7 +86,6 @@ protected:
|
|||||||
EC_KEY* pkey;
|
EC_KEY* pkey;
|
||||||
bool fSet;
|
bool fSet;
|
||||||
|
|
||||||
static EC_KEY* GenerateDeterministicKey(const uint256& base, uint32 n, bool private_key);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<CKey> pointer;
|
typedef boost::shared_ptr<CKey> pointer;
|
||||||
@@ -123,13 +122,26 @@ public:
|
|||||||
EC_KEY_free(pkey);
|
EC_KEY_free(pkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
CKey(const uint256& base, uint32 seq, bool private_key) : fSet(true)
|
|
||||||
|
static uint256 PassPhraseToKey(const std::string& passPhrase);
|
||||||
|
static EC_KEY* GenerateRootDeterministicKey(const uint256& passPhrase);
|
||||||
|
static EC_KEY* GeneratePublicDeterministicKey(const uint160& family, EC_POINT* rootPub, int n);
|
||||||
|
static EC_KEY* GeneratePrivateDeterministicKey(const uint160& family, BIGNUM* rootPriv, int n);
|
||||||
|
|
||||||
|
CKey(const uint256& passPhrase) : fSet(true)
|
||||||
{
|
{
|
||||||
pkey=GenerateDeterministicKey(base, seq, private_key);
|
pkey = GenerateRootDeterministicKey(passPhrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint256 GetBaseFromString(const std::string& base);
|
CKey(const uint160& base, EC_POINT* rootPubKey, int n) : fSet(true)
|
||||||
static uint256 GetRandomBase(void);
|
{ // public deterministic key
|
||||||
|
pkey = GeneratePublicDeterministicKey(base, rootPubKey, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
CKey(const uint160& base, BIGNUM* rootPrivKey, int n) : fSet(true)
|
||||||
|
{ // private deterministic key
|
||||||
|
pkey = GeneratePrivateDeterministicKey(base, rootPrivKey, n);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsNull() const
|
bool IsNull() const
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user