More work on core ledger and transaction processing code.

This commit is contained in:
JoelKatz
2011-11-22 15:42:03 -08:00
parent 41309b6f72
commit 6c7fd5f195
10 changed files with 253 additions and 106 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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--;
}

View File

@@ -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);
};

View File

@@ -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
{

View File

@@ -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) :
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();
}

View File

@@ -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

View File

@@ -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
View File

@@ -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)

View File

@@ -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;
}