mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 10:35:50 +00:00
More work on core ledger and transaction processing code.
This commit is contained in:
@@ -12,9 +12,20 @@ public:
|
||||
private:
|
||||
uint160 mAccountID;
|
||||
uint64 mBalance;
|
||||
uint32 mAccountSeq, mFirstValidLedger, mLastValidLedger;
|
||||
uint32 mAccountSeq;
|
||||
bool mValid;
|
||||
|
||||
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
|
||||
|
||||
@@ -31,15 +31,13 @@ use public keys in compressed form using
|
||||
EC_KEY_set_conv_form(POINT_CONVERSION_COMPRESS) -- so our public keys are
|
||||
actually 33 bytes.
|
||||
|
||||
Account IDs are based on the uncompressed public key. Form a 65-byte
|
||||
quantity consisting of a single byte with the value 4, the 32-byte X of the
|
||||
public key followed by the 32-byte Y of the public key. Apply SHA256 to this
|
||||
65-byte quantity. Apply RIPEMD160 to the result.
|
||||
Account IDs are based on the compressed public key. Apply SHA512 to the
|
||||
33-byte public key. Apply RIPEMD160 to the first 256 bits of the result.
|
||||
|
||||
The resulting 20-byte value is the account ID.
|
||||
|
||||
|
||||
2) Transaction (source/signed format) 148-bytes
|
||||
2) Transaction (source/signed format) 145-bytes
|
||||
|
||||
Fields:
|
||||
1) 20-byte destination account
|
||||
@@ -48,10 +46,9 @@ Fields:
|
||||
4) 4-byte source ledger index, unsigned BE integer
|
||||
5) 4-byte arbitrary source tag, unsigned BE integer
|
||||
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 76-byte contents of fields 1-6
|
||||
8) 72-byte prefix 0x54584E00 signature of 73-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.
|
||||
|
||||
3) Transaction (ledger format)
|
||||
|
||||
119
Ledger.cpp
119
Ledger.cpp
@@ -11,14 +11,14 @@
|
||||
using namespace boost;
|
||||
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,
|
||||
uint64 feeHeld, uint64 timeStamp, uint32 ledgerSeq)
|
||||
: mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash),
|
||||
mFeeHeld(feeHeld), mTimeStamp(timeStamp), mLedgerSeq(ledgerSeq)
|
||||
mFeeHeld(feeHeld), mTimeStamp(timeStamp), mLedgerSeq(ledgerSeq), mCurrent(false)
|
||||
{
|
||||
updateHash();
|
||||
}
|
||||
@@ -40,8 +40,83 @@ void Ledger::addRaw(Serializer &s)
|
||||
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
|
||||
@@ -86,7 +161,7 @@ void Ledger::setTo(newcoin::FullLedger& ledger)
|
||||
for(int n=0; n<numTrans; 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];
|
||||
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_seqnum( db->getInt("seqnum"));
|
||||
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
|
||||
bool Ledger::addTransaction(TransactionPtr trans,bool checkDuplicate)
|
||||
bool Ledger::addTransaction(Transaction::pointer trans,bool checkDuplicate)
|
||||
{
|
||||
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.
|
||||
void Ledger::addTransactionAllowNeg(TransactionPtr trans)
|
||||
void Ledger::addTransactionAllowNeg(Transaction::pointer trans)
|
||||
{
|
||||
uint160 fromAddress=protobufTo160(trans->from());
|
||||
|
||||
@@ -376,8 +451,8 @@ void Ledger::recalculate(bool recursive)
|
||||
|
||||
mAccounts.clear();
|
||||
mAccounts=mParent->getAccounts();
|
||||
list<TransactionPtr> firstTransactions=mTransactions;
|
||||
list<TransactionPtr> secondTransactions=mDiscardedTransactions;
|
||||
list<Transaction::pointer> firstTransactions=mTransactions;
|
||||
list<Transaction::pointer> secondTransactions=mDiscardedTransactions;
|
||||
|
||||
mTransactions.clear();
|
||||
mDiscardedTransactions.clear();
|
||||
@@ -386,12 +461,12 @@ void Ledger::recalculate(bool recursive)
|
||||
secondTransactions.sort(gTransactionSorter);
|
||||
|
||||
// don't check balances until the end
|
||||
BOOST_FOREACH(TransactionPtr trans,firstTransactions)
|
||||
BOOST_FOREACH(Transaction::pointer trans,firstTransactions)
|
||||
{
|
||||
addTransactionAllowNeg(trans);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(TransactionPtr trans,secondTransactions)
|
||||
BOOST_FOREACH(Transaction::pointer trans,secondTransactions)
|
||||
{
|
||||
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
|
||||
|
||||
@@ -452,18 +527,18 @@ void Ledger::parentAddedTransaction(TransactionPtr cause)
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(TransactionPtr disTrans,mDiscardedTransactions)
|
||||
BOOST_FOREACH(Transaction::pointer disTrans,mDiscardedTransactions)
|
||||
{
|
||||
if( Transaction::isEqual(needle,disTrans) ) return(true);
|
||||
}
|
||||
@@ -489,8 +564,8 @@ bool Ledger::isCompatible(Ledger::pointer other)
|
||||
|
||||
void Ledger::mergeIn(Ledger::pointer other)
|
||||
{
|
||||
list<TransactionPtr>& otherTransactions=other->getTransactions();
|
||||
BOOST_FOREACH(TransactionPtr trans,otherTransactions)
|
||||
list<Transaction::pointer>& otherTransactions=other->getTransactions();
|
||||
BOOST_FOREACH(Transaction::pointer trans,otherTransactions)
|
||||
{
|
||||
addTransactionAllowNeg(trans);
|
||||
}
|
||||
@@ -516,9 +591,9 @@ void Ledger::correctAccount(const uint160& address)
|
||||
list<uint160> effected;
|
||||
|
||||
// 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)
|
||||
{
|
||||
Account fromAccount=mAccounts[address];
|
||||
@@ -536,10 +611,10 @@ void Ledger::correctAccount(const uint160& address)
|
||||
mAccounts[destAddress]=destAccount;
|
||||
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;
|
||||
|
||||
iter=list<TransactionPtr>::reverse_iterator(temp);
|
||||
iter=list<Transaction::pointer>::reverse_iterator(temp);
|
||||
}else break;
|
||||
}else iter--;
|
||||
}
|
||||
|
||||
45
Ledger.h
45
Ledger.h
@@ -17,37 +17,58 @@
|
||||
|
||||
class Ledger : public boost::enable_shared_from_this<Ledger>
|
||||
{ // The basic Ledger structure, can be opened, closed, or synching
|
||||
public:
|
||||
|
||||
typedef boost::shared_ptr<Ledger> pointer;
|
||||
|
||||
enum TransResult
|
||||
{
|
||||
TR_ERROR =-1,
|
||||
TR_SUCCESS =0,
|
||||
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:
|
||||
uint256 mHash, mParentHash, mTransHash, mAccountHash;
|
||||
uint64 mFeeHeld, mTimeStamp;
|
||||
uint32 mLedgerSeq;
|
||||
bool mCurrent;
|
||||
|
||||
SHAMap::pointer mTransactionMap, mAccountStateMap;
|
||||
|
||||
mutable boost::recursive_mutex mLock;
|
||||
|
||||
protected:
|
||||
void updateHash();
|
||||
|
||||
bool addAccountState(AccountState::pointer);
|
||||
bool updateAccountState(AccountState::pointer);
|
||||
bool addTransaction(Transaction::pointer);
|
||||
bool delTransaction(const uint256& id);
|
||||
|
||||
public:
|
||||
Ledger(uint32 index); // used for the starting bootstrap ledger
|
||||
Ledger(const Ledger &ledger);
|
||||
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||
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
|
||||
void addRaw(Serializer &s);
|
||||
|
||||
virtual uint256 getHash() const;
|
||||
uint256 getHash() const;
|
||||
const uint256& getParentHash() const { return mParentHash; }
|
||||
const uint256& getTransHash() const { return mTransHash; }
|
||||
const uint256& getAccountHash() const { return mAccountHash; }
|
||||
@@ -55,15 +76,21 @@ public:
|
||||
uint64 getTimeStamp() const { return mTimeStamp; }
|
||||
uint32 getLedgerSeq() const { return mLedgerSeq; }
|
||||
|
||||
// low level functions
|
||||
SHAMap::pointer getTransactionMap() { return mTransactionMap; }
|
||||
SHAMap::pointer getAccountStateMap() { return mAccountStateMap; }
|
||||
|
||||
TransResult applyTransaction(TransactionPtr& trans);
|
||||
TransResult removeTransaction(TransactionPtr& trans);
|
||||
TransResult hasTransaction(TransactionPtr& trans);
|
||||
|
||||
// mid level functions
|
||||
AccountState::pointer getAccountState(const uint160& acctID);
|
||||
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 isCompatible(Ledger::pointer other);
|
||||
bool isCompatible(boost::shared_ptr<Ledger> other);
|
||||
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
|
||||
{ // Identifies a node in a SHA256 hash
|
||||
public:
|
||||
typedef boost::shared_ptr<SHAMapNode> pointer;
|
||||
|
||||
|
||||
private:
|
||||
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
|
||||
public:
|
||||
typedef boost::shared_ptr<SHAMapItem> pointer;
|
||||
@@ -98,7 +102,6 @@ public:
|
||||
virtual void dump(void);
|
||||
};
|
||||
|
||||
|
||||
class SHAMapLeafNode : public SHAMapNode
|
||||
{
|
||||
friend class SHAMap;
|
||||
@@ -166,6 +169,12 @@ public:
|
||||
virtual void dump(void);
|
||||
};
|
||||
|
||||
enum SHAMapException
|
||||
{
|
||||
MissingNode=1,
|
||||
InvalidNode=2
|
||||
};
|
||||
|
||||
|
||||
class SHAMap
|
||||
{
|
||||
|
||||
@@ -11,65 +11,83 @@ Transaction::Transaction() : mTransactionID(0), mAccountFrom(0), mAccountTo(0),
|
||||
{
|
||||
}
|
||||
|
||||
Transaction::Transaction(TransStatus status, LocalAccount& fromLocalAccount, Account& fromAccount,
|
||||
uint32 fromSeq, const uint160& toAccount, uint64 amount, uint32 ident, uint32 ledger) :
|
||||
mAccountTo(toAccount), mAmount(amount), mFromAccountSeq(fromSeq), mSourceLedger(ledger),
|
||||
mIdent(ident), mInLedger(0), mStatus(NEW)
|
||||
Transaction::Transaction(TransStatus status, LocalAccount& fromLocalAccount, uint32 fromSeq,
|
||||
const uint160& toAccount, uint64 amount, uint32 ident, uint32 ledger) :
|
||||
mAccountTo(toAccount), mAmount(amount), mFromAccountSeq(fromSeq), mSourceLedger(ledger),
|
||||
mIdent(ident), mInLedger(0), mStatus(NEW)
|
||||
{
|
||||
assert(fromAccount.getAddress()==fromLocalAccount.mAddress);
|
||||
assert(fromLocalAccount.mAmount>=amount);
|
||||
assert((fromSeq+1)==fromLocalAccount.mSeqNum);
|
||||
|
||||
mAccountFrom=fromAccount.getAddress();
|
||||
mAccountFrom=fromLocalAccount.getAddress();
|
||||
updateFee();
|
||||
mFromPubKey.SetPubKey(fromLocalAccount.peekPubKey().GetPubKey());
|
||||
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)
|
||||
{
|
||||
if( (mAmount==0) || (mSourceLedger==0) || (mAccountTo==0) )
|
||||
return false;
|
||||
if(mpAccountFrom == Account::pointer())
|
||||
if(mAccountFrom!=fromLocalAccount.mAddress)
|
||||
return false;
|
||||
if((mpAccountFrom->getAddress()!=fromLocalAccount.mAddress) || (mAccountFrom!=mpAccountFrom->getAddress()))
|
||||
return false;
|
||||
|
||||
Serializer::pointer signBuf(getRawUnsigned());
|
||||
Serializer::pointer signBuf=getRaw(true);
|
||||
if(!signBuf->makeSignature(mSignature, fromLocalAccount.peekPrivKey()))
|
||||
return false;
|
||||
signBuf->addRaw(mSignature);
|
||||
mTransactionID=signBuf->getSHA512Half();
|
||||
updateID();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Transaction::updateFee()
|
||||
{ // for now, all transactions have a 1,000 unit fee
|
||||
mFee=1000;
|
||||
}
|
||||
|
||||
bool Transaction::checkSign() const
|
||||
{
|
||||
if(mpAccountFrom == Account::pointer()) return false;
|
||||
if(mpAccountFrom->getAddress()!=mAccountFrom) return false;
|
||||
|
||||
Serializer::pointer toSign(getRawUnsigned());
|
||||
return toSign->checkSignature(mSignature, mpAccountFrom->peekPubKey());
|
||||
return mFromPubKey.Verify(getRaw(true)->getSHA512Half(), mSignature);
|
||||
}
|
||||
|
||||
Serializer::pointer Transaction::getRawUnsigned() const
|
||||
Serializer::pointer Transaction::getRaw(bool prefix) const
|
||||
{
|
||||
Serializer::pointer ret(new Serializer(104));
|
||||
ret->add32(0x54584e00u);
|
||||
ret->addRaw(mpAccountFrom->peekPubKey().GetPubKey());
|
||||
Serializer::pointer ret(new Serializer(77));
|
||||
if(prefix) ret->add32(0x54584e00u);
|
||||
ret->addRaw(mFromPubKey.GetPubKey());
|
||||
ret->add64(mAmount);
|
||||
ret->add32(mFromAccountSeq);
|
||||
ret->add32(mInLedger);
|
||||
ret->add32(mIdent);
|
||||
assert( (prefix&&(ret->getLength()==77)) || (!prefix&&(ret->getLength()==73)) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
Serializer::pointer Transaction::getRawSigned() const
|
||||
Serializer::pointer Transaction::getSigned() const
|
||||
{
|
||||
Serializer::pointer ret(getRawUnsigned());
|
||||
Serializer::pointer ret(getRaw(false));
|
||||
ret->addRaw(mSignature);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Transaction::updateID()
|
||||
{
|
||||
if( (mpAccountFrom!=Account::pointer()) && (mpAccountFrom->getAddress()==mAccountFrom))
|
||||
mTransactionID=getRawSigned()->getSHA512Half();
|
||||
mTransactionID=getSigned()->getSHA512Half();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
#include "key.h"
|
||||
#include "uint256.h"
|
||||
#include "newcoin.pb.h"
|
||||
#include "Hanko.h"
|
||||
@@ -31,40 +32,42 @@ class LocalAccount;
|
||||
class Transaction : public boost::enable_shared_from_this<Transaction>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef boost::shared_ptr<Transaction> pointer;
|
||||
|
||||
static const uint32 TransSignMagic=0x54584E00; // "TXN"
|
||||
|
||||
private:
|
||||
uint256 mTransactionID;
|
||||
uint160 mAccountFrom, mAccountTo;
|
||||
uint64 mAmount;
|
||||
uint64 mAmount, mFee;
|
||||
uint32 mFromAccountSeq, mSourceLedger, mIdent;
|
||||
CKey mFromPubKey;
|
||||
std::vector<unsigned char> mSignature;
|
||||
|
||||
uint32 mInLedger;
|
||||
TransStatus mStatus;
|
||||
|
||||
Account::pointer mpAccountFrom;
|
||||
|
||||
public:
|
||||
Transaction();
|
||||
Transaction(const std::vector<unsigned char> rawTransaction);
|
||||
Transaction(const std::string sqlReply);
|
||||
Transaction(TransStatus Status, LocalAccount& fromLocal, Account& from,
|
||||
uint32 fromSeq, const uint160& to, uint64 amount, uint32 ident, uint32 ledger);
|
||||
|
||||
void setFromAccountPointer(Account::pointer af) { mpAccountFrom=af; }
|
||||
Transaction(const std::vector<unsigned char>& rawTransaction, bool validate);
|
||||
Transaction(TransStatus Status, LocalAccount& fromLocal, uint32 fromSeq, const uint160& to, uint64 amount,
|
||||
uint32 ident, uint32 ledger);
|
||||
|
||||
bool sign(LocalAccount& fromLocalAccount);
|
||||
bool checkSign() const;
|
||||
void updateID();
|
||||
void updateFee();
|
||||
|
||||
Serializer::pointer getRawUnsigned() const;
|
||||
Serializer::pointer getRawSigned() const;
|
||||
Serializer::pointer getRaw(bool prefix) const;
|
||||
Serializer::pointer getSigned() const;
|
||||
|
||||
const uint256& getID() const { return mTransactionID; }
|
||||
const uint160& getFromAccount() const { return mAccountFrom; }
|
||||
const uint160& getToAccount() const { return mAccountTo; }
|
||||
uint64 getAmount() const { return mAmount; }
|
||||
uint64 getFee() const { return mFee; }
|
||||
uint32 getFromAccountSeq() const { return mFromAccountSeq; }
|
||||
uint32 getSourceLedger() const { return mSourceLedger; }
|
||||
uint32 getIdent() const { return mIdent; }
|
||||
@@ -72,8 +75,7 @@ public:
|
||||
uint32 getLedger() const { return mInLedger; }
|
||||
TransStatus getStatus() const { return mStatus; }
|
||||
|
||||
void setStatus(TransStatus st);
|
||||
void setLedger(uint32 Ledger);
|
||||
void setStatus(TransStatus status, uint32 ledgerSeq);
|
||||
|
||||
bool operator<(const Transaction &) const;
|
||||
bool operator>(const Transaction &) const;
|
||||
@@ -83,6 +85,4 @@ public:
|
||||
bool operator>=(const Transaction &) const;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Transaction> TransactionPtr;
|
||||
|
||||
#endif
|
||||
|
||||
9
Wallet.h
9
Wallet.h
@@ -27,6 +27,9 @@ public:
|
||||
bool signRaw(Serializer::pointer, std::vector<unsigned char>& signature);
|
||||
bool checkSignRaw(Serializer::pointer, int signaturePosition=-1, int signedData=-1);
|
||||
CKey& peekPrivKey() { return mPrivateKey; }
|
||||
CKey& peekPubKey() { return mPublicKey; }
|
||||
|
||||
const uint160& getAddress(void) const { return mAddress; }
|
||||
};
|
||||
|
||||
class Wallet : public CBasicKeyStore
|
||||
@@ -35,8 +38,8 @@ class Wallet : public CBasicKeyStore
|
||||
|
||||
|
||||
|
||||
TransactionPtr createTransaction(LocalAccount& fromAccount, uint160& destAddr, int64 amount);
|
||||
bool commitTransaction(TransactionPtr trans);
|
||||
Transaction::pointer createTransaction(LocalAccount& fromAccount, uint160& destAddr, int64 amount);
|
||||
bool commitTransaction(Transaction::pointer trans);
|
||||
|
||||
LocalAccount* consolidateAccountOfSize(int64 amount);
|
||||
|
||||
@@ -51,7 +54,7 @@ public:
|
||||
std::string sendMoneyToAddress(uint160& destAddress, int64 amount);
|
||||
|
||||
// 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 "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:
|
||||
// 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;
|
||||
//
|
||||
// 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))
|
||||
goto err;
|
||||
|
||||
EC_KEY_set_conv_form(eckey,POINT_CONVERSION_COMPRESSED);
|
||||
EC_KEY_set_private_key(eckey,priv_key);
|
||||
EC_KEY_set_public_key(eckey,pub_key);
|
||||
|
||||
@@ -100,6 +87,7 @@ public:
|
||||
CKey()
|
||||
{
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||
fSet = false;
|
||||
@@ -108,6 +96,7 @@ public:
|
||||
CKey(const CKey& b)
|
||||
{
|
||||
pkey = EC_KEY_dup(b.pkey);
|
||||
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
||||
fSet = b.fSet;
|
||||
@@ -135,6 +124,7 @@ public:
|
||||
{
|
||||
if (!EC_KEY_generate_key(pkey))
|
||||
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
||||
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||
fSet = true;
|
||||
}
|
||||
|
||||
@@ -143,6 +133,7 @@ public:
|
||||
const unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
||||
return false;
|
||||
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
@@ -161,6 +152,7 @@ public:
|
||||
if (!EC_KEY_regenerate_key(pkey,bn))
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
|
||||
BN_clear_free(bn);
|
||||
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
@@ -196,6 +188,7 @@ public:
|
||||
const unsigned char* pbegin = &vchPubKey[0];
|
||||
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
|
||||
return false;
|
||||
EC_KEY_set_conv_form(pkey,POINT_CONVERSION_COMPRESSED);
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
@@ -224,7 +217,7 @@ public:
|
||||
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
|
||||
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
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_UINT256_H
|
||||
#define BITCOIN_UINT256_H
|
||||
#ifndef NEWCOIN_UINT256_H
|
||||
#define NEWCOIN_UINT256_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 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; }
|
||||
|
||||
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