From 6c7fd5f1956f19754b6640df5a1eb56b2202ec64 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 22 Nov 2011 15:42:03 -0800 Subject: [PATCH] More work on core ledger and transaction processing code. --- AccountState.h | 13 ++++- BinaryFormats.txt | 13 ++--- Ledger.cpp | 119 +++++++++++++++++++++++++++++++++++++--------- Ledger.h | 45 ++++++++++++++---- SHAMap.h | 13 ++++- Transaction.cpp | 74 +++++++++++++++++----------- Transaction.h | 28 +++++------ Wallet.h | 9 ++-- key.h | 27 ++++------- uint256.h | 18 ++++++- 10 files changed, 253 insertions(+), 106 deletions(-) diff --git a/AccountState.h b/AccountState.h index 4090465542..615fe5847f 100644 --- a/AccountState.h +++ b/AccountState.h @@ -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&); // 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 diff --git a/BinaryFormats.txt b/BinaryFormats.txt index cc59ea0f0b..5f862c535d 100644 --- a/BinaryFormats.txt +++ b/BinaryFormats.txt @@ -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) diff --git a/Ledger.cpp b/Ledger.cpp index bafd613f2e..ee8ded7141 100644 --- a/Ledger.cpp +++ b/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()getAmount()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()getAmount()) return TR_INSUFF; + if(fromAccount->getSeq()>trans->getFromAccountSeq()) return TR_PASTASEQ; + if(fromAccount->getSeq()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; ngetNextRow()) { - 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 firstTransactions=mTransactions; - list secondTransactions=mDiscardedTransactions; + list firstTransactions=mTransactions; + list 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& otherTransactions=other->getTransactions(); - BOOST_FOREACH(TransactionPtr trans,otherTransactions) + list& otherTransactions=other->getTransactions(); + BOOST_FOREACH(Transaction::pointer trans,otherTransactions) { addTransactionAllowNeg(trans); } @@ -516,9 +591,9 @@ void Ledger::correctAccount(const uint160& address) list effected; // do this in reverse so we take of the higher seqnum first - for( list::reverse_iterator iter=mTransactions.rbegin(); iter != mTransactions.rend(); ) + for( list::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::iterator temp=mTransactions.erase( --iter.base() ); + list::iterator temp=mTransactions.erase( --iter.base() ); if(fromAccount.first>=0) break; - iter=list::reverse_iterator(temp); + iter=list::reverse_iterator(temp); }else break; }else iter--; } diff --git a/Ledger.h b/Ledger.h index 612bdc993c..66d99e8294 100644 --- a/Ledger.h +++ b/Ledger.h @@ -17,37 +17,58 @@ class Ledger : public boost::enable_shared_from_this { // The basic Ledger structure, can be opened, closed, or synching +public: + + typedef boost::shared_ptr 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 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 other); bool signLedger(std::vector &signature, const LocalHanko &hanko, int32 confidence); }; diff --git a/SHAMap.h b/SHAMap.h index e363acda3c..479ea4feb6 100644 --- a/SHAMap.h +++ b/SHAMap.h @@ -19,6 +19,10 @@ class SHAMap; class SHAMapNode { // Identifies a node in a SHA256 hash +public: + typedef boost::shared_ptr 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 +class SHAMapItem { // an item stored in a SHAMap public: typedef boost::shared_ptr 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 { diff --git a/Transaction.cpp b/Transaction.cpp index 844c319935..0a2f7f8698 100644 --- a/Transaction.cpp +++ b/Transaction.cpp @@ -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 &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 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(); } diff --git a/Transaction.h b/Transaction.h index b41079fd75..1d787c52d1 100644 --- a/Transaction.h +++ b/Transaction.h @@ -5,6 +5,7 @@ #include #include +#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 { public: + + typedef boost::shared_ptr 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 mSignature; uint32 mInLedger; TransStatus mStatus; - Account::pointer mpAccountFrom; public: Transaction(); - Transaction(const std::vector 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& 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 TransactionPtr; - #endif diff --git a/Wallet.h b/Wallet.h index 088932ad25..a92cbecfb8 100644 --- a/Wallet.h +++ b/Wallet.h @@ -27,6 +27,9 @@ public: bool signRaw(Serializer::pointer, std::vector& 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); }; diff --git a/key.h b/key.h index 97f29cfc70..dcf3542b75 100644 --- a/key.h +++ b/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& vchSig) + bool Verify(uint256 hash, const std::vector& vchSig) const { // -1 = error, 0 = bad sig, 1 = good if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) diff --git a/uint256.h b/uint256.h index 7facb3308c..ae2e7690c8 100644 --- a/uint256.h +++ b/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 @@ -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; +}