mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 10:05:48 +00:00
More work on core ledger and transaction processing code.
This commit is contained in:
@@ -12,9 +12,20 @@ public:
|
|||||||
private:
|
private:
|
||||||
uint160 mAccountID;
|
uint160 mAccountID;
|
||||||
uint64 mBalance;
|
uint64 mBalance;
|
||||||
uint32 mAccountSeq, mFirstValidLedger, mLastValidLedger;
|
uint32 mAccountSeq;
|
||||||
|
bool mValid;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
AccountState(const uint160& mAccountID); // new account
|
||||||
|
AccountState(const std::vector<unsigned char>&); // raw form
|
||||||
|
|
||||||
|
const uint160& getAccountID() const { return mAccountID; }
|
||||||
|
uint64 getBalance() const { return mBalance; }
|
||||||
|
uint32 getSeq() const { return mAccountSeq; }
|
||||||
|
|
||||||
|
bool charge(uint64 a) { mBalance+=a; }
|
||||||
|
bool credit(uint64 a) { mBalance-=a; }
|
||||||
|
void incSeq(void) { mAccountSeq++; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -31,15 +31,13 @@ use public keys in compressed form using
|
|||||||
EC_KEY_set_conv_form(POINT_CONVERSION_COMPRESS) -- so our public keys are
|
EC_KEY_set_conv_form(POINT_CONVERSION_COMPRESS) -- so our public keys are
|
||||||
actually 33 bytes.
|
actually 33 bytes.
|
||||||
|
|
||||||
Account IDs are based on the uncompressed public key. Form a 65-byte
|
Account IDs are based on the compressed public key. Apply SHA512 to the
|
||||||
quantity consisting of a single byte with the value 4, the 32-byte X of the
|
33-byte public key. Apply RIPEMD160 to the first 256 bits of the result.
|
||||||
public key followed by the 32-byte Y of the public key. Apply SHA256 to this
|
|
||||||
65-byte quantity. Apply RIPEMD160 to the result.
|
|
||||||
|
|
||||||
The resulting 20-byte value is the account ID.
|
The resulting 20-byte value is the account ID.
|
||||||
|
|
||||||
|
|
||||||
2) Transaction (source/signed format) 148-bytes
|
2) Transaction (source/signed format) 145-bytes
|
||||||
|
|
||||||
Fields:
|
Fields:
|
||||||
1) 20-byte destination account
|
1) 20-byte destination account
|
||||||
@@ -48,10 +46,9 @@ Fields:
|
|||||||
4) 4-byte source ledger index, unsigned BE integer
|
4) 4-byte source ledger index, unsigned BE integer
|
||||||
5) 4-byte arbitrary source tag, unsigned BE integer
|
5) 4-byte arbitrary source tag, unsigned BE integer
|
||||||
6) 33-byte source public key
|
6) 33-byte source public key
|
||||||
7) 3-byte padding (must be zero on send, ignore on receive)
|
8) 72-byte prefix 0x54584E00 signature of 73-byte contents of fields 1-6
|
||||||
8) 72-byte prefix 0x54584E00 signature of 76-byte contents of fields 1-6
|
|
||||||
|
|
||||||
The transaction ID is the first 256-bits of the SHA512 hash of the 148 byte
|
The transaction ID is the first 256-bits of the SHA512 hash of the 145 byte
|
||||||
signed transaction.
|
signed transaction.
|
||||||
|
|
||||||
3) Transaction (ledger format)
|
3) Transaction (ledger format)
|
||||||
|
|||||||
119
Ledger.cpp
119
Ledger.cpp
@@ -11,14 +11,14 @@
|
|||||||
using namespace boost;
|
using namespace boost;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Ledger::Ledger(uint32 index) : mFeeHeld(0), mTimeStamp(0), mLedgerSeq(index)
|
Ledger::Ledger(uint32 index) : mFeeHeld(0), mTimeStamp(0), mLedgerSeq(index), mCurrent(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||||
uint64 feeHeld, uint64 timeStamp, uint32 ledgerSeq)
|
uint64 feeHeld, uint64 timeStamp, uint32 ledgerSeq)
|
||||||
: mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash),
|
: mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash),
|
||||||
mFeeHeld(feeHeld), mTimeStamp(timeStamp), mLedgerSeq(ledgerSeq)
|
mFeeHeld(feeHeld), mTimeStamp(timeStamp), mLedgerSeq(ledgerSeq), mCurrent(false)
|
||||||
{
|
{
|
||||||
updateHash();
|
updateHash();
|
||||||
}
|
}
|
||||||
@@ -40,8 +40,83 @@ void Ledger::addRaw(Serializer &s)
|
|||||||
s.add64(mTimeStamp);
|
s.add64(mTimeStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::TransResult Ledger::applyTransaction(TransactionPtr &trans)
|
AccountState::pointer Ledger::getAccountState(const uint160& accountID)
|
||||||
{
|
{
|
||||||
|
ScopedLock l(mTransactionMap->Lock());
|
||||||
|
SHAMapItem::pointer item=mTransactionMap->getItem(uint160to256(accountID));
|
||||||
|
if(item==NULL) return AccountState::pointer();
|
||||||
|
return AccountState::pointer(new AccountState(item->getData()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction::pointer Ledger::getTransaction(const uint256& transID)
|
||||||
|
{
|
||||||
|
ScopedLock l(mTransactionMap->Lock());
|
||||||
|
SHAMapItem::pointer item=mTransactionMap->getItem(transID);
|
||||||
|
if(item==NULL) return Transaction::pointer();
|
||||||
|
Transaction *t=new Transaction(item->getData(), true);
|
||||||
|
if(t->getStatus()==NEW) t->setStatus(mCurrent ? INCLUDED : COMMITTED, mLedgerSeq);
|
||||||
|
return Transaction::pointer(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ledger::TransResult Ledger::applyTransaction(Transaction::pointer trans)
|
||||||
|
{
|
||||||
|
ScopedLock l(mLock);
|
||||||
|
if(trans->getSourceLedger()<mLedgerSeq) return TR_BADLSEQ;
|
||||||
|
if(trans->getAmount()<trans->getFee()) return TR_TOOSMALL;
|
||||||
|
if((mTransactionMap==NULL) || (mAccountStateMap==NULL)) return TR_ERROR;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// already applied?
|
||||||
|
Transaction::pointer dupTrans=getTransaction(trans->getID());
|
||||||
|
if(dupTrans!=NULL) return TR_ALREADY;
|
||||||
|
|
||||||
|
// accounts exist?
|
||||||
|
AccountState::pointer fromAccount=getAccountState(trans->getFromAccount());
|
||||||
|
AccountState::pointer toAccount=getAccountState(trans->getToAccount());
|
||||||
|
if((fromAccount==NULL)||(toAccount==NULL)) return TR_BADACCT;
|
||||||
|
|
||||||
|
// pass sanity checks?
|
||||||
|
if(fromAccount->getBalance()<trans->getAmount()) return TR_INSUFF;
|
||||||
|
if(fromAccount->getSeq()>trans->getFromAccountSeq()) return TR_PASTASEQ;
|
||||||
|
if(fromAccount->getSeq()<trans->getFromAccountSeq()) return TR_PREASEQ;
|
||||||
|
|
||||||
|
// apply
|
||||||
|
fromAccount->charge(trans->getAmount());
|
||||||
|
fromAccount->incSeq();
|
||||||
|
toAccount->credit(trans->getAmount()-trans->getFee());
|
||||||
|
mFeeHeld+=trans->getFee();
|
||||||
|
trans->setStatus(INCLUDED, mLedgerSeq);
|
||||||
|
|
||||||
|
updateAccountState(fromAccount);
|
||||||
|
updateAccountState(toAccount);
|
||||||
|
addTransaction(trans);
|
||||||
|
|
||||||
|
return TR_SUCCESS;
|
||||||
|
}
|
||||||
|
catch (SHAMapException)
|
||||||
|
{
|
||||||
|
return TR_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ledger::TransResult Ledger::removeTransaction(Transaction::pointer trans)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Ledger::TransResult Ledger::hasTransaction(Transaction::pointer trans)
|
||||||
|
{
|
||||||
|
ScopedLock l(mLock);
|
||||||
|
if(mTransactionMap==NULL) return TR_ERROR;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Transaction::pointer t=getTransaction(trans->getID());
|
||||||
|
if(t==NULL) return TR_NOTFOUND;
|
||||||
|
return TR_SUCCESS;
|
||||||
|
}
|
||||||
|
catch (SHAMapException)
|
||||||
|
{
|
||||||
|
return TR_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -86,7 +161,7 @@ void Ledger::setTo(newcoin::FullLedger& ledger)
|
|||||||
for(int n=0; n<numTrans; n++)
|
for(int n=0; n<numTrans; n++)
|
||||||
{
|
{
|
||||||
const newcoin::Transaction& trans=ledger.transactions(n);
|
const newcoin::Transaction& trans=ledger.transactions(n);
|
||||||
mTransactions.push_back(TransactionPtr(new newcoin::Transaction(trans)));
|
mTransactions.push_back(Transaction::pointer(new newcoin::Transaction(trans)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +209,7 @@ bool Ledger::load(const uint256& hash)
|
|||||||
unsigned char tbuf[1000];
|
unsigned char tbuf[1000];
|
||||||
while(db->getNextRow())
|
while(db->getNextRow())
|
||||||
{
|
{
|
||||||
TransactionPtr trans=TransactionPtr(new newcoin::Transaction());
|
Transaction::pointer trans=Transaction::pointer(new newcoin::Transaction());
|
||||||
trans->set_amount( db->getBigInt("Amount"));
|
trans->set_amount( db->getBigInt("Amount"));
|
||||||
trans->set_seqnum( db->getInt("seqnum"));
|
trans->set_seqnum( db->getInt("seqnum"));
|
||||||
trans->set_ledgerindex( db->getInt("ledgerIndex"));
|
trans->set_ledgerindex( db->getInt("ledgerIndex"));
|
||||||
@@ -262,7 +337,7 @@ uint64 Ledger::getAmount(std::string address)
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
// returns true if the from account has enough for the transaction and seq num is correct
|
// returns true if the from account has enough for the transaction and seq num is correct
|
||||||
bool Ledger::addTransaction(TransactionPtr trans,bool checkDuplicate)
|
bool Ledger::addTransaction(Transaction::pointer trans,bool checkDuplicate)
|
||||||
{
|
{
|
||||||
if(checkDuplicate && hasTransaction(trans)) return(false);
|
if(checkDuplicate && hasTransaction(trans)) return(false);
|
||||||
|
|
||||||
@@ -316,7 +391,7 @@ bool Ledger::addTransaction(TransactionPtr trans,bool checkDuplicate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't check the amounts. We will do this at the end.
|
// Don't check the amounts. We will do this at the end.
|
||||||
void Ledger::addTransactionAllowNeg(TransactionPtr trans)
|
void Ledger::addTransactionAllowNeg(Transaction::pointer trans)
|
||||||
{
|
{
|
||||||
uint160 fromAddress=protobufTo160(trans->from());
|
uint160 fromAddress=protobufTo160(trans->from());
|
||||||
|
|
||||||
@@ -376,8 +451,8 @@ void Ledger::recalculate(bool recursive)
|
|||||||
|
|
||||||
mAccounts.clear();
|
mAccounts.clear();
|
||||||
mAccounts=mParent->getAccounts();
|
mAccounts=mParent->getAccounts();
|
||||||
list<TransactionPtr> firstTransactions=mTransactions;
|
list<Transaction::pointer> firstTransactions=mTransactions;
|
||||||
list<TransactionPtr> secondTransactions=mDiscardedTransactions;
|
list<Transaction::pointer> secondTransactions=mDiscardedTransactions;
|
||||||
|
|
||||||
mTransactions.clear();
|
mTransactions.clear();
|
||||||
mDiscardedTransactions.clear();
|
mDiscardedTransactions.clear();
|
||||||
@@ -386,12 +461,12 @@ void Ledger::recalculate(bool recursive)
|
|||||||
secondTransactions.sort(gTransactionSorter);
|
secondTransactions.sort(gTransactionSorter);
|
||||||
|
|
||||||
// don't check balances until the end
|
// don't check balances until the end
|
||||||
BOOST_FOREACH(TransactionPtr trans,firstTransactions)
|
BOOST_FOREACH(Transaction::pointer trans,firstTransactions)
|
||||||
{
|
{
|
||||||
addTransactionAllowNeg(trans);
|
addTransactionAllowNeg(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(TransactionPtr trans,secondTransactions)
|
BOOST_FOREACH(Transaction::pointer trans,secondTransactions)
|
||||||
{
|
{
|
||||||
addTransactionAllowNeg(trans);
|
addTransactionAllowNeg(trans);
|
||||||
}
|
}
|
||||||
@@ -408,7 +483,7 @@ void Ledger::recalculate(bool recursive)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Ledger::parentAddedTransaction(TransactionPtr cause)
|
void Ledger::parentAddedTransaction(Transaction::pointer cause)
|
||||||
{
|
{
|
||||||
// TODO: optimize we can make this more efficient at some point. For now just redo everything
|
// TODO: optimize we can make this more efficient at some point. For now just redo everything
|
||||||
|
|
||||||
@@ -452,18 +527,18 @@ void Ledger::parentAddedTransaction(TransactionPtr cause)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// look for discarded transactions
|
// look for discarded transactions
|
||||||
BOOST_FOREACH(TransactionPtr trans,)
|
BOOST_FOREACH(Transaction::pointer trans,)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ledger::hasTransaction(TransactionPtr needle)
|
bool Ledger::hasTransaction(Transaction::pointer needle)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(TransactionPtr trans,mTransactions)
|
BOOST_FOREACH(Transaction::pointer trans,mTransactions)
|
||||||
{
|
{
|
||||||
if( Transaction::isEqual(needle,trans) ) return(true);
|
if( Transaction::isEqual(needle,trans) ) return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(TransactionPtr disTrans,mDiscardedTransactions)
|
BOOST_FOREACH(Transaction::pointer disTrans,mDiscardedTransactions)
|
||||||
{
|
{
|
||||||
if( Transaction::isEqual(needle,disTrans) ) return(true);
|
if( Transaction::isEqual(needle,disTrans) ) return(true);
|
||||||
}
|
}
|
||||||
@@ -489,8 +564,8 @@ bool Ledger::isCompatible(Ledger::pointer other)
|
|||||||
|
|
||||||
void Ledger::mergeIn(Ledger::pointer other)
|
void Ledger::mergeIn(Ledger::pointer other)
|
||||||
{
|
{
|
||||||
list<TransactionPtr>& otherTransactions=other->getTransactions();
|
list<Transaction::pointer>& otherTransactions=other->getTransactions();
|
||||||
BOOST_FOREACH(TransactionPtr trans,otherTransactions)
|
BOOST_FOREACH(Transaction::pointer trans,otherTransactions)
|
||||||
{
|
{
|
||||||
addTransactionAllowNeg(trans);
|
addTransactionAllowNeg(trans);
|
||||||
}
|
}
|
||||||
@@ -516,9 +591,9 @@ void Ledger::correctAccount(const uint160& address)
|
|||||||
list<uint160> effected;
|
list<uint160> effected;
|
||||||
|
|
||||||
// do this in reverse so we take of the higher seqnum first
|
// do this in reverse so we take of the higher seqnum first
|
||||||
for( list<TransactionPtr>::reverse_iterator iter=mTransactions.rbegin(); iter != mTransactions.rend(); )
|
for( list<Transaction::pointer>::reverse_iterator iter=mTransactions.rbegin(); iter != mTransactions.rend(); )
|
||||||
{
|
{
|
||||||
TransactionPtr trans= *iter;
|
Transaction::pointer trans= *iter;
|
||||||
if(protobufTo160(trans->from()) == address)
|
if(protobufTo160(trans->from()) == address)
|
||||||
{
|
{
|
||||||
Account fromAccount=mAccounts[address];
|
Account fromAccount=mAccounts[address];
|
||||||
@@ -536,10 +611,10 @@ void Ledger::correctAccount(const uint160& address)
|
|||||||
mAccounts[destAddress]=destAccount;
|
mAccounts[destAddress]=destAccount;
|
||||||
if(destAccount.first<0) effected.push_back(destAddress);
|
if(destAccount.first<0) effected.push_back(destAddress);
|
||||||
|
|
||||||
list<TransactionPtr>::iterator temp=mTransactions.erase( --iter.base() );
|
list<Transaction::pointer>::iterator temp=mTransactions.erase( --iter.base() );
|
||||||
if(fromAccount.first>=0) break;
|
if(fromAccount.first>=0) break;
|
||||||
|
|
||||||
iter=list<TransactionPtr>::reverse_iterator(temp);
|
iter=list<Transaction::pointer>::reverse_iterator(temp);
|
||||||
}else break;
|
}else break;
|
||||||
}else iter--;
|
}else iter--;
|
||||||
}
|
}
|
||||||
|
|||||||
45
Ledger.h
45
Ledger.h
@@ -17,37 +17,58 @@
|
|||||||
|
|
||||||
class Ledger : public boost::enable_shared_from_this<Ledger>
|
class Ledger : public boost::enable_shared_from_this<Ledger>
|
||||||
{ // The basic Ledger structure, can be opened, closed, or synching
|
{ // The basic Ledger structure, can be opened, closed, or synching
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<Ledger> pointer;
|
||||||
|
|
||||||
enum TransResult
|
enum TransResult
|
||||||
{
|
{
|
||||||
TR_ERROR =-1,
|
TR_ERROR =-1,
|
||||||
TR_SUCCESS =0,
|
TR_SUCCESS =0,
|
||||||
TR_NOTFOUND =1,
|
TR_NOTFOUND =1,
|
||||||
TR_ALREADY =2
|
TR_ALREADY =2,
|
||||||
|
TR_BADTRANS =3, // the transaction itself is corrupt
|
||||||
|
TR_BADACCT =4, // one of the accounts is invalid
|
||||||
|
TR_INSUFF =5, // the sending account is broke
|
||||||
|
TR_PASTASEQ =6, // account is past this transaction
|
||||||
|
TR_PREASEQ =7, // account is missing transactions before this
|
||||||
|
TR_BADLSEQ =8, // ledger too early
|
||||||
|
TR_TOOSMALL =9, // amount is less than Tx fee
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
typedef boost::shared_ptr<Ledger> pointer;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint256 mHash, mParentHash, mTransHash, mAccountHash;
|
uint256 mHash, mParentHash, mTransHash, mAccountHash;
|
||||||
uint64 mFeeHeld, mTimeStamp;
|
uint64 mFeeHeld, mTimeStamp;
|
||||||
uint32 mLedgerSeq;
|
uint32 mLedgerSeq;
|
||||||
|
bool mCurrent;
|
||||||
|
|
||||||
SHAMap::pointer mTransactionMap, mAccountStateMap;
|
SHAMap::pointer mTransactionMap, mAccountStateMap;
|
||||||
|
|
||||||
|
mutable boost::recursive_mutex mLock;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void updateHash();
|
void updateHash();
|
||||||
|
|
||||||
|
bool addAccountState(AccountState::pointer);
|
||||||
|
bool updateAccountState(AccountState::pointer);
|
||||||
|
bool addTransaction(Transaction::pointer);
|
||||||
|
bool delTransaction(const uint256& id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ledger(uint32 index); // used for the starting bootstrap ledger
|
Ledger(uint32 index); // used for the starting bootstrap ledger
|
||||||
Ledger(const Ledger &ledger);
|
Ledger(const Ledger &ledger);
|
||||||
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||||
uint64 feeHeld, uint64 timeStamp, uint32 ledgerSeq); // used for received ledgers
|
uint64 feeHeld, uint64 timeStamp, uint32 ledgerSeq); // used for received ledgers
|
||||||
|
|
||||||
|
void setCurrent(void) { mCurrent=true; }
|
||||||
|
void clearCurrent(void) { mCurrent=false; }
|
||||||
|
bool isCurrent(void) { return mCurrent; }
|
||||||
|
|
||||||
// ledger signature operations
|
// ledger signature operations
|
||||||
void addRaw(Serializer &s);
|
void addRaw(Serializer &s);
|
||||||
|
|
||||||
virtual uint256 getHash() const;
|
uint256 getHash() const;
|
||||||
const uint256& getParentHash() const { return mParentHash; }
|
const uint256& getParentHash() const { return mParentHash; }
|
||||||
const uint256& getTransHash() const { return mTransHash; }
|
const uint256& getTransHash() const { return mTransHash; }
|
||||||
const uint256& getAccountHash() const { return mAccountHash; }
|
const uint256& getAccountHash() const { return mAccountHash; }
|
||||||
@@ -55,15 +76,21 @@ public:
|
|||||||
uint64 getTimeStamp() const { return mTimeStamp; }
|
uint64 getTimeStamp() const { return mTimeStamp; }
|
||||||
uint32 getLedgerSeq() const { return mLedgerSeq; }
|
uint32 getLedgerSeq() const { return mLedgerSeq; }
|
||||||
|
|
||||||
|
// low level functions
|
||||||
SHAMap::pointer getTransactionMap() { return mTransactionMap; }
|
SHAMap::pointer getTransactionMap() { return mTransactionMap; }
|
||||||
SHAMap::pointer getAccountStateMap() { return mAccountStateMap; }
|
SHAMap::pointer getAccountStateMap() { return mAccountStateMap; }
|
||||||
|
|
||||||
TransResult applyTransaction(TransactionPtr& trans);
|
// mid level functions
|
||||||
TransResult removeTransaction(TransactionPtr& trans);
|
AccountState::pointer getAccountState(const uint160& acctID);
|
||||||
TransResult hasTransaction(TransactionPtr& trans);
|
Transaction::pointer getTransaction(const uint256& transID);
|
||||||
|
|
||||||
|
// high level functions
|
||||||
|
TransResult applyTransaction(Transaction::pointer trans);
|
||||||
|
TransResult removeTransaction(Transaction::pointer trans);
|
||||||
|
TransResult hasTransaction(Transaction::pointer trans);
|
||||||
|
|
||||||
bool closeLedger();
|
bool closeLedger();
|
||||||
bool isCompatible(Ledger::pointer other);
|
bool isCompatible(boost::shared_ptr<Ledger> other);
|
||||||
bool signLedger(std::vector<unsigned char> &signature, const LocalHanko &hanko, int32 confidence);
|
bool signLedger(std::vector<unsigned char> &signature, const LocalHanko &hanko, int32 confidence);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
13
SHAMap.h
13
SHAMap.h
@@ -19,6 +19,10 @@ class SHAMap;
|
|||||||
|
|
||||||
class SHAMapNode
|
class SHAMapNode
|
||||||
{ // Identifies a node in a SHA256 hash
|
{ // Identifies a node in a SHA256 hash
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<SHAMapNode> pointer;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uint256 smMasks[11]; // AND with hash to get node id
|
static uint256 smMasks[11]; // AND with hash to get node id
|
||||||
|
|
||||||
@@ -59,7 +63,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SHAMapItem : public boost::enable_shared_from_this<SHAMapItem>
|
class SHAMapItem
|
||||||
{ // an item stored in a SHAMap
|
{ // an item stored in a SHAMap
|
||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<SHAMapItem> pointer;
|
typedef boost::shared_ptr<SHAMapItem> pointer;
|
||||||
@@ -98,7 +102,6 @@ public:
|
|||||||
virtual void dump(void);
|
virtual void dump(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SHAMapLeafNode : public SHAMapNode
|
class SHAMapLeafNode : public SHAMapNode
|
||||||
{
|
{
|
||||||
friend class SHAMap;
|
friend class SHAMap;
|
||||||
@@ -166,6 +169,12 @@ public:
|
|||||||
virtual void dump(void);
|
virtual void dump(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SHAMapException
|
||||||
|
{
|
||||||
|
MissingNode=1,
|
||||||
|
InvalidNode=2
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class SHAMap
|
class SHAMap
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,65 +11,83 @@ Transaction::Transaction() : mTransactionID(0), mAccountFrom(0), mAccountTo(0),
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::Transaction(TransStatus status, LocalAccount& fromLocalAccount, Account& fromAccount,
|
Transaction::Transaction(TransStatus status, LocalAccount& fromLocalAccount, uint32 fromSeq,
|
||||||
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(fromAccount.getAddress()==fromLocalAccount.mAddress);
|
|
||||||
assert(fromLocalAccount.mAmount>=amount);
|
assert(fromLocalAccount.mAmount>=amount);
|
||||||
assert((fromSeq+1)==fromLocalAccount.mSeqNum);
|
mAccountFrom=fromLocalAccount.getAddress();
|
||||||
|
updateFee();
|
||||||
mAccountFrom=fromAccount.getAddress();
|
mFromPubKey.SetPubKey(fromLocalAccount.peekPubKey().GetPubKey());
|
||||||
sign(fromLocalAccount);
|
sign(fromLocalAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transaction::Transaction(const std::vector<unsigned char> &t, bool validate) : mStatus(INVALID)
|
||||||
|
{
|
||||||
|
Serializer s(t);
|
||||||
|
if(s.getLength()<145) return;
|
||||||
|
if(!s.get160(mAccountTo, 0)) return;
|
||||||
|
if(!s.get64(mAmount, 20)) return;
|
||||||
|
if(!s.get32(mFromAccountSeq, 28)) return;
|
||||||
|
if(!s.get32(mSourceLedger, 32)) return;
|
||||||
|
if(!s.get32(mIdent, 36)) return;
|
||||||
|
if(!s.getRaw(mSignature, 69, 72)) return;
|
||||||
|
|
||||||
|
std::vector<unsigned char> pubKey;
|
||||||
|
if(!s.getRaw(pubKey, 40, 33)) return;
|
||||||
|
if(!mFromPubKey.SetPubKey(pubKey)) return;
|
||||||
|
updateID();
|
||||||
|
|
||||||
|
if(validate && !checkSign()) return;
|
||||||
|
|
||||||
|
mStatus=NEW;
|
||||||
|
}
|
||||||
|
|
||||||
bool Transaction::sign(LocalAccount& fromLocalAccount)
|
bool Transaction::sign(LocalAccount& fromLocalAccount)
|
||||||
{
|
{
|
||||||
if( (mAmount==0) || (mSourceLedger==0) || (mAccountTo==0) )
|
if( (mAmount==0) || (mSourceLedger==0) || (mAccountTo==0) )
|
||||||
return false;
|
return false;
|
||||||
if(mpAccountFrom == Account::pointer())
|
if(mAccountFrom!=fromLocalAccount.mAddress)
|
||||||
return false;
|
return false;
|
||||||
if((mpAccountFrom->getAddress()!=fromLocalAccount.mAddress) || (mAccountFrom!=mpAccountFrom->getAddress()))
|
Serializer::pointer signBuf=getRaw(true);
|
||||||
return false;
|
|
||||||
|
|
||||||
Serializer::pointer signBuf(getRawUnsigned());
|
|
||||||
if(!signBuf->makeSignature(mSignature, fromLocalAccount.peekPrivKey()))
|
if(!signBuf->makeSignature(mSignature, fromLocalAccount.peekPrivKey()))
|
||||||
return false;
|
return false;
|
||||||
signBuf->addRaw(mSignature);
|
updateID();
|
||||||
mTransactionID=signBuf->getSHA512Half();
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Transaction::updateFee()
|
||||||
|
{ // for now, all transactions have a 1,000 unit fee
|
||||||
|
mFee=1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Transaction::checkSign() const
|
bool Transaction::checkSign() const
|
||||||
{
|
{
|
||||||
if(mpAccountFrom == Account::pointer()) return false;
|
return mFromPubKey.Verify(getRaw(true)->getSHA512Half(), mSignature);
|
||||||
if(mpAccountFrom->getAddress()!=mAccountFrom) return false;
|
|
||||||
|
|
||||||
Serializer::pointer toSign(getRawUnsigned());
|
|
||||||
return toSign->checkSignature(mSignature, mpAccountFrom->peekPubKey());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Serializer::pointer Transaction::getRawUnsigned() const
|
Serializer::pointer Transaction::getRaw(bool prefix) const
|
||||||
{
|
{
|
||||||
Serializer::pointer ret(new Serializer(104));
|
Serializer::pointer ret(new Serializer(77));
|
||||||
ret->add32(0x54584e00u);
|
if(prefix) ret->add32(0x54584e00u);
|
||||||
ret->addRaw(mpAccountFrom->peekPubKey().GetPubKey());
|
ret->addRaw(mFromPubKey.GetPubKey());
|
||||||
ret->add64(mAmount);
|
ret->add64(mAmount);
|
||||||
ret->add32(mFromAccountSeq);
|
ret->add32(mFromAccountSeq);
|
||||||
ret->add32(mInLedger);
|
ret->add32(mInLedger);
|
||||||
ret->add32(mIdent);
|
ret->add32(mIdent);
|
||||||
|
assert( (prefix&&(ret->getLength()==77)) || (!prefix&&(ret->getLength()==73)) );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serializer::pointer Transaction::getRawSigned() const
|
Serializer::pointer Transaction::getSigned() const
|
||||||
{
|
{
|
||||||
Serializer::pointer ret(getRawUnsigned());
|
Serializer::pointer ret(getRaw(false));
|
||||||
ret->addRaw(mSignature);
|
ret->addRaw(mSignature);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transaction::updateID()
|
void Transaction::updateID()
|
||||||
{
|
{
|
||||||
if( (mpAccountFrom!=Account::pointer()) && (mpAccountFrom->getAddress()==mAccountFrom))
|
mTransactionID=getSigned()->getSHA512Half();
|
||||||
mTransactionID=getRawSigned()->getSHA512Half();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
|
|
||||||
|
#include "key.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "newcoin.pb.h"
|
#include "newcoin.pb.h"
|
||||||
#include "Hanko.h"
|
#include "Hanko.h"
|
||||||
@@ -31,40 +32,42 @@ class LocalAccount;
|
|||||||
class Transaction : public boost::enable_shared_from_this<Transaction>
|
class Transaction : public boost::enable_shared_from_this<Transaction>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<Transaction> pointer;
|
||||||
|
|
||||||
static const uint32 TransSignMagic=0x54584E00; // "TXN"
|
static const uint32 TransSignMagic=0x54584E00; // "TXN"
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint256 mTransactionID;
|
uint256 mTransactionID;
|
||||||
uint160 mAccountFrom, mAccountTo;
|
uint160 mAccountFrom, mAccountTo;
|
||||||
uint64 mAmount;
|
uint64 mAmount, mFee;
|
||||||
uint32 mFromAccountSeq, mSourceLedger, mIdent;
|
uint32 mFromAccountSeq, mSourceLedger, mIdent;
|
||||||
|
CKey mFromPubKey;
|
||||||
std::vector<unsigned char> mSignature;
|
std::vector<unsigned char> mSignature;
|
||||||
|
|
||||||
uint32 mInLedger;
|
uint32 mInLedger;
|
||||||
TransStatus mStatus;
|
TransStatus mStatus;
|
||||||
|
|
||||||
Account::pointer mpAccountFrom;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Transaction();
|
Transaction();
|
||||||
Transaction(const std::vector<unsigned char> rawTransaction);
|
Transaction(const std::vector<unsigned char>& rawTransaction, bool validate);
|
||||||
Transaction(const std::string sqlReply);
|
Transaction(TransStatus Status, LocalAccount& fromLocal, uint32 fromSeq, const uint160& to, uint64 amount,
|
||||||
Transaction(TransStatus Status, LocalAccount& fromLocal, Account& from,
|
uint32 ident, uint32 ledger);
|
||||||
uint32 fromSeq, const uint160& to, uint64 amount, uint32 ident, uint32 ledger);
|
|
||||||
|
|
||||||
void setFromAccountPointer(Account::pointer af) { mpAccountFrom=af; }
|
|
||||||
|
|
||||||
bool sign(LocalAccount& fromLocalAccount);
|
bool sign(LocalAccount& fromLocalAccount);
|
||||||
bool checkSign() const;
|
bool checkSign() const;
|
||||||
void updateID();
|
void updateID();
|
||||||
|
void updateFee();
|
||||||
|
|
||||||
Serializer::pointer getRawUnsigned() const;
|
Serializer::pointer getRaw(bool prefix) const;
|
||||||
Serializer::pointer getRawSigned() const;
|
Serializer::pointer getSigned() const;
|
||||||
|
|
||||||
const uint256& getID() const { return mTransactionID; }
|
const uint256& getID() const { return mTransactionID; }
|
||||||
const uint160& getFromAccount() const { return mAccountFrom; }
|
const uint160& getFromAccount() const { return mAccountFrom; }
|
||||||
const uint160& getToAccount() const { return mAccountTo; }
|
const uint160& getToAccount() const { return mAccountTo; }
|
||||||
uint64 getAmount() const { return mAmount; }
|
uint64 getAmount() const { return mAmount; }
|
||||||
|
uint64 getFee() const { return mFee; }
|
||||||
uint32 getFromAccountSeq() const { return mFromAccountSeq; }
|
uint32 getFromAccountSeq() const { return mFromAccountSeq; }
|
||||||
uint32 getSourceLedger() const { return mSourceLedger; }
|
uint32 getSourceLedger() const { return mSourceLedger; }
|
||||||
uint32 getIdent() const { return mIdent; }
|
uint32 getIdent() const { return mIdent; }
|
||||||
@@ -72,8 +75,7 @@ public:
|
|||||||
uint32 getLedger() const { return mInLedger; }
|
uint32 getLedger() const { return mInLedger; }
|
||||||
TransStatus getStatus() const { return mStatus; }
|
TransStatus getStatus() const { return mStatus; }
|
||||||
|
|
||||||
void setStatus(TransStatus st);
|
void setStatus(TransStatus status, uint32 ledgerSeq);
|
||||||
void setLedger(uint32 Ledger);
|
|
||||||
|
|
||||||
bool operator<(const Transaction &) const;
|
bool operator<(const Transaction &) const;
|
||||||
bool operator>(const Transaction &) const;
|
bool operator>(const Transaction &) const;
|
||||||
@@ -83,6 +85,4 @@ public:
|
|||||||
bool operator>=(const Transaction &) const;
|
bool operator>=(const Transaction &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::shared_ptr<Transaction> TransactionPtr;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
9
Wallet.h
9
Wallet.h
@@ -27,6 +27,9 @@ public:
|
|||||||
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, int signaturePosition=-1, int signedData=-1);
|
||||||
CKey& peekPrivKey() { return mPrivateKey; }
|
CKey& peekPrivKey() { return mPrivateKey; }
|
||||||
|
CKey& peekPubKey() { return mPublicKey; }
|
||||||
|
|
||||||
|
const uint160& getAddress(void) const { return mAddress; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Wallet : public CBasicKeyStore
|
class Wallet : public CBasicKeyStore
|
||||||
@@ -35,8 +38,8 @@ class Wallet : public CBasicKeyStore
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
TransactionPtr createTransaction(LocalAccount& fromAccount, uint160& destAddr, int64 amount);
|
Transaction::pointer createTransaction(LocalAccount& fromAccount, uint160& destAddr, int64 amount);
|
||||||
bool commitTransaction(TransactionPtr trans);
|
bool commitTransaction(Transaction::pointer trans);
|
||||||
|
|
||||||
LocalAccount* consolidateAccountOfSize(int64 amount);
|
LocalAccount* consolidateAccountOfSize(int64 amount);
|
||||||
|
|
||||||
@@ -51,7 +54,7 @@ public:
|
|||||||
std::string sendMoneyToAddress(uint160& destAddress, int64 amount);
|
std::string sendMoneyToAddress(uint160& destAddress, int64 amount);
|
||||||
|
|
||||||
// you may need to update your balances
|
// you may need to update your balances
|
||||||
void transactionChanged(TransactionPtr trans);
|
void transactionChanged(Transaction::pointer trans);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
27
key.h
27
key.h
@@ -17,24 +17,10 @@
|
|||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
|
|
||||||
// secp160k1
|
|
||||||
// const unsigned int PRIVATE_KEY_SIZE = 192;
|
|
||||||
// const unsigned int PUBLIC_KEY_SIZE = 41;
|
|
||||||
// const unsigned int SIGNATURE_SIZE = 48;
|
|
||||||
//
|
|
||||||
// secp192k1
|
|
||||||
// const unsigned int PRIVATE_KEY_SIZE = 222;
|
|
||||||
// const unsigned int PUBLIC_KEY_SIZE = 49;
|
|
||||||
// const unsigned int SIGNATURE_SIZE = 57;
|
|
||||||
//
|
|
||||||
// secp224k1
|
|
||||||
// const unsigned int PRIVATE_KEY_SIZE = 250;
|
|
||||||
// const unsigned int PUBLIC_KEY_SIZE = 57;
|
|
||||||
// const unsigned int SIGNATURE_SIZE = 66;
|
|
||||||
//
|
|
||||||
// secp256k1:
|
// secp256k1:
|
||||||
// const unsigned int PRIVATE_KEY_SIZE = 279;
|
// const unsigned int PRIVATE_KEY_SIZE = 279;
|
||||||
// const unsigned int PUBLIC_KEY_SIZE = 65;
|
// const unsigned int PUBLIC_KEY_SIZE = 65; // but we don't use full keys
|
||||||
|
// const unsigned int COMPUB_KEY_SIZE = 33;
|
||||||
// const unsigned int SIGNATURE_SIZE = 72;
|
// const unsigned int SIGNATURE_SIZE = 72;
|
||||||
//
|
//
|
||||||
// see www.keylength.com
|
// see www.keylength.com
|
||||||
@@ -61,6 +47,7 @@ int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
|
|||||||
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
|
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
EC_KEY_set_conv_form(eckey,POINT_CONVERSION_COMPRESSED);
|
||||||
EC_KEY_set_private_key(eckey,priv_key);
|
EC_KEY_set_private_key(eckey,priv_key);
|
||||||
EC_KEY_set_public_key(eckey,pub_key);
|
EC_KEY_set_public_key(eckey,pub_key);
|
||||||
|
|
||||||
@@ -100,6 +87,7 @@ public:
|
|||||||
CKey()
|
CKey()
|
||||||
{
|
{
|
||||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||||
|
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||||
if (pkey == NULL)
|
if (pkey == NULL)
|
||||||
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||||
fSet = false;
|
fSet = false;
|
||||||
@@ -108,6 +96,7 @@ public:
|
|||||||
CKey(const CKey& b)
|
CKey(const CKey& b)
|
||||||
{
|
{
|
||||||
pkey = EC_KEY_dup(b.pkey);
|
pkey = EC_KEY_dup(b.pkey);
|
||||||
|
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||||
if (pkey == NULL)
|
if (pkey == NULL)
|
||||||
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
||||||
fSet = b.fSet;
|
fSet = b.fSet;
|
||||||
@@ -135,6 +124,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (!EC_KEY_generate_key(pkey))
|
if (!EC_KEY_generate_key(pkey))
|
||||||
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
||||||
|
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||||
fSet = true;
|
fSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +133,7 @@ public:
|
|||||||
const unsigned char* pbegin = &vchPrivKey[0];
|
const unsigned char* pbegin = &vchPrivKey[0];
|
||||||
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
||||||
return false;
|
return false;
|
||||||
|
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||||
fSet = true;
|
fSet = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -161,6 +152,7 @@ public:
|
|||||||
if (!EC_KEY_regenerate_key(pkey,bn))
|
if (!EC_KEY_regenerate_key(pkey,bn))
|
||||||
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
|
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
|
||||||
BN_clear_free(bn);
|
BN_clear_free(bn);
|
||||||
|
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||||
fSet = true;
|
fSet = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -196,6 +188,7 @@ public:
|
|||||||
const unsigned char* pbegin = &vchPubKey[0];
|
const unsigned char* pbegin = &vchPubKey[0];
|
||||||
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
|
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
|
||||||
return false;
|
return false;
|
||||||
|
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||||
fSet = true;
|
fSet = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -224,7 +217,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
|
bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig) const
|
||||||
{
|
{
|
||||||
// -1 = error, 0 = bad sig, 1 = good
|
// -1 = error, 0 = bad sig, 1 = good
|
||||||
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
|
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
|
||||||
|
|||||||
18
uint256.h
18
uint256.h
@@ -2,8 +2,8 @@
|
|||||||
// Copyright (c) 2011 The Bitcoin developers
|
// Copyright (c) 2011 The Bitcoin developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
#ifndef BITCOIN_UINT256_H
|
#ifndef NEWCOIN_UINT256_H
|
||||||
#define BITCOIN_UINT256_H
|
#define NEWCOIN_UINT256_H
|
||||||
|
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@@ -584,6 +584,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline bool operator==(const uint256& a, uint64 b) { return (base_uint256)a == b; }
|
inline bool operator==(const uint256& a, uint64 b) { return (base_uint256)a == b; }
|
||||||
inline bool operator!=(const uint256& a, uint64 b) { return (base_uint256)a != b; }
|
inline bool operator!=(const uint256& a, uint64 b) { return (base_uint256)a != b; }
|
||||||
inline const uint256 operator<<(const base_uint256& a, unsigned int shift) { return uint256(a) <<= shift; }
|
inline const uint256 operator<<(const base_uint256& a, unsigned int shift) { return uint256(a) <<= shift; }
|
||||||
@@ -633,6 +634,19 @@ inline const uint256 operator|(const uint256& a, const uint256& b) { return
|
|||||||
inline const uint256 operator+(const uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; }
|
inline const uint256 operator+(const uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; }
|
||||||
inline const uint256 operator-(const uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; }
|
inline const uint256 operator-(const uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; }
|
||||||
|
|
||||||
|
static uint256 uint160to256(const uint160& u)
|
||||||
|
{
|
||||||
|
uint256 m;
|
||||||
|
memcpy(((char *) &m)+(sizeof(m)-sizeof(u)), &u, sizeof(u));
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint160 uint256to160(const uint256& u)
|
||||||
|
{
|
||||||
|
uint160 m;
|
||||||
|
memcpy((char *) &m, &u, sizeof(m));
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user