mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 10:35:50 +00:00
Bugfixes and new code. Ledger unit test now successfully creates a local
account, creates an initial ledger, closes the initial ledger and opens a new ledger, creates a second account, and adds a transaction to transfer funds to the open ledger.
This commit is contained in:
@@ -5,9 +5,13 @@ AccountState::AccountState(const std::vector<unsigned char>& v)
|
||||
{
|
||||
Serializer s(v);
|
||||
mValid=false;
|
||||
if(!s.get160(mAccountID, 0)) return;
|
||||
if(!s.get64(mBalance, 20)) return;
|
||||
if(!s.get32(mAccountSeq, 28)) return;
|
||||
if(!s.get160(mAccountID, 0)) { assert(false); return; }
|
||||
if(!s.get64(mBalance, 20)) { assert(false); return; }
|
||||
if(!s.get32(mAccountSeq, 28)) { assert(false); return; }
|
||||
#ifdef DEBUG
|
||||
std::cerr << "SerializeAccount >> " << mAccountID.GetHex() << ", " << mBalance << ", " << mAccountSeq <<
|
||||
std::endl;
|
||||
#endif
|
||||
mValid=true;
|
||||
}
|
||||
|
||||
@@ -20,5 +24,12 @@ std::vector<unsigned char> AccountState::getRaw() const
|
||||
s.add160(mAccountID);
|
||||
s.add64(mBalance);
|
||||
s.add32(mAccountSeq);
|
||||
#ifdef DEBUG
|
||||
std::cerr << "SerializeAccount << " << mAccountID.GetHex() << ", " << mBalance << ", " << mAccountSeq <<
|
||||
std::endl;
|
||||
uint64 test;
|
||||
assert(s.get64(test, 20));
|
||||
assert(test==mBalance);
|
||||
#endif
|
||||
return s.getData();
|
||||
}
|
||||
|
||||
50
Ledger.cpp
50
Ledger.cpp
@@ -32,7 +32,8 @@ Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint25
|
||||
updateHash();
|
||||
}
|
||||
|
||||
Ledger::Ledger(Ledger &prevLedger, uint64 ts) : mTimeStamp(ts), mClosed(false)
|
||||
Ledger::Ledger(Ledger &prevLedger, uint64 ts) : mTimeStamp(ts), mClosed(false),
|
||||
mTransactionMap(new SHAMap()), mAccountStateMap(prevLedger.mAccountStateMap)
|
||||
{
|
||||
prevLedger.updateHash();
|
||||
mParentHash=prevLedger.mHash;
|
||||
@@ -87,6 +88,7 @@ bool Ledger::addAccountState(AccountState::pointer state)
|
||||
|
||||
bool Ledger::addTransaction(Transaction::pointer trans)
|
||||
{ // low-level - just add to table
|
||||
assert(!!trans->getID());
|
||||
SHAMapItem::pointer item(new SHAMapItem(trans->getID(), trans->getSigned()->getData()));
|
||||
return mTransactionMap->addGiveItem(item);
|
||||
}
|
||||
@@ -109,8 +111,17 @@ Transaction::pointer Ledger::getTransaction(const uint256& transID)
|
||||
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(trans->getSourceLedger()>mLedgerSeq) return TR_BADLSEQ;
|
||||
|
||||
if(trans->getAmount()<trans->getFee())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Transaction for " << trans->getAmount() << ", but fee is " <<
|
||||
trans->getFee() << std::endl;
|
||||
#endif
|
||||
return TR_TOOSMALL;
|
||||
}
|
||||
|
||||
if(!mTransactionMap || !mAccountStateMap) return TR_ERROR;
|
||||
try
|
||||
{
|
||||
@@ -132,7 +143,18 @@ Ledger::TransResult Ledger::applyTransaction(Transaction::pointer trans)
|
||||
if(!fromAccount || !toAccount) return TR_BADACCT;
|
||||
|
||||
// pass sanity checks?
|
||||
if(fromAccount->getBalance()<trans->getAmount()) return TR_INSUFF;
|
||||
if(fromAccount->getBalance()<trans->getAmount())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Transaction for " << trans->getAmount() << ", but account has " <<
|
||||
fromAccount->getBalance() << std::endl;
|
||||
#endif
|
||||
return TR_INSUFF;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if(fromAccount->getSeq()!=trans->getFromAccountSeq())
|
||||
std::cerr << "aSeq=" << fromAccount->getSeq() << ", tSeq=" << trans->getFromAccountSeq() << std::endl;
|
||||
#endif
|
||||
if(fromAccount->getSeq()>trans->getFromAccountSeq()) return TR_PASTASEQ;
|
||||
if(fromAccount->getSeq()<trans->getFromAccountSeq()) return TR_PREASEQ;
|
||||
|
||||
@@ -226,13 +248,27 @@ bool Ledger::unitTest(void)
|
||||
std::cerr << "Account2: " << la2.GetHex() << std::endl;
|
||||
#endif
|
||||
|
||||
Ledger newLedger(la1, 10000);
|
||||
Ledger::pointer ledger(new Ledger(la1, 100000));
|
||||
l1.mAmount=100000;
|
||||
|
||||
ledger=Ledger::pointer(new Ledger(*ledger, 0));
|
||||
|
||||
AccountState::pointer as=newLedger.getAccountState(la1);
|
||||
AccountState::pointer as=ledger->getAccountState(la1);
|
||||
assert(as);
|
||||
as=newLedger.getAccountState(la2);
|
||||
assert(as->getBalance()==100000);
|
||||
assert(as->getSeq()==0);
|
||||
as=ledger->getAccountState(la2);
|
||||
assert(!as);
|
||||
|
||||
Transaction::pointer t(new Transaction(NEW, l1, l1.mSeqNum, l2.getAddress(), 2500, 0, 1));
|
||||
assert(!!t->getID());
|
||||
|
||||
Ledger::TransResult tr=ledger->applyTransaction(t);
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Transaction: " << tr << std::endl;
|
||||
#endif
|
||||
assert(tr==TR_SUCCESS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,33 +7,32 @@
|
||||
int Serializer::add16(uint16 i)
|
||||
{
|
||||
int ret=mData.size();
|
||||
for(int j=0; j<sizeof(i); j++)
|
||||
{
|
||||
mData.push_back((unsigned char) (i&0xff));
|
||||
i>>=8;
|
||||
}
|
||||
mData.push_back((unsigned char)(i>>8));
|
||||
mData.push_back((unsigned char)(i&0xff));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::add32(uint32 i)
|
||||
{
|
||||
int ret=mData.size();
|
||||
for(int j=0; j<sizeof(i); j++)
|
||||
{
|
||||
mData.push_back((unsigned char) (i&0xff));
|
||||
i>>=8;
|
||||
}
|
||||
mData.push_back((unsigned char)(i>>24));
|
||||
mData.push_back((unsigned char)((i>>16)&0xff));
|
||||
mData.push_back((unsigned char)((i>>8)&0xff));
|
||||
mData.push_back((unsigned char)(i&0xff));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::add64(uint64 i)
|
||||
{
|
||||
int ret=mData.size();
|
||||
for(int j=0; j<sizeof(i); j++)
|
||||
{
|
||||
mData.push_back((unsigned char) (i&0xff));
|
||||
i>>=8;
|
||||
}
|
||||
mData.push_back((unsigned char)(i>>56));
|
||||
mData.push_back((unsigned char)((i>>48)&0xff));
|
||||
mData.push_back((unsigned char)((i>>40)&0xff));
|
||||
mData.push_back((unsigned char)((i>>32)&0xff));
|
||||
mData.push_back((unsigned char)((i>>24)&0xff));
|
||||
mData.push_back((unsigned char)((i>>16)&0xff));
|
||||
mData.push_back((unsigned char)((i>>8)&0xff));
|
||||
mData.push_back((unsigned char)(i&0xff));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -60,59 +59,51 @@ int Serializer::addRaw(const std::vector<unsigned char> &vector)
|
||||
|
||||
bool Serializer::get16(uint16& o, int offset) const
|
||||
{
|
||||
o=0;
|
||||
if((offset+sizeof(o))>mData.size()) return false;
|
||||
for(int i=0, o=0; i<sizeof(o); i++)
|
||||
{
|
||||
o<<=8;
|
||||
o|=mData.at(offset++);
|
||||
}
|
||||
if((offset+2)>mData.size()) return false;
|
||||
o=mData.at(offset++);
|
||||
o<<=8; o|=mData.at(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::get32(uint32& o, int offset) const
|
||||
{
|
||||
o=0;
|
||||
if((offset+sizeof(o))>mData.size()) return false;
|
||||
for(int i=0, o=0; i<sizeof(o); i++)
|
||||
{
|
||||
o<<=8;
|
||||
o|=mData.at(offset++);
|
||||
}
|
||||
if((offset+4)>mData.size()) return false;
|
||||
o=mData.at(offset++);
|
||||
o<<=8; o|=mData.at(offset++); o<<=8; o|=mData.at(offset++);
|
||||
o<<=8; o|=mData.at(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::get64(uint64& o, int offset) const
|
||||
{
|
||||
o=0;
|
||||
if((offset+sizeof(o))>mData.size()) return false;
|
||||
for(int i=0, o=0; i<sizeof(o); i++)
|
||||
{
|
||||
o<<=8;
|
||||
o|=mData.at(offset++);
|
||||
}
|
||||
if((offset+8)>mData.size()) return false;
|
||||
o=mData.at(offset++);
|
||||
o<<=8; o|=mData.at(offset++); o<<=8; o|=mData.at(offset++);
|
||||
o<<=8; o|=mData.at(offset++); o<<=8; o|=mData.at(offset++);
|
||||
o<<=8; o|=mData.at(offset++); o<<=8; o|=mData.at(offset++);
|
||||
o<<=8; o|=mData.at(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::get160(uint160& o, int offset) const
|
||||
{
|
||||
if((offset+sizeof(o))>mData.size()) return false;
|
||||
memcpy(&o, &(mData.front())+offset, sizeof(o));
|
||||
if((offset+20)>mData.size()) return false;
|
||||
memcpy(&o, &(mData.front())+offset, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::get256(uint256& o, int offset) const
|
||||
{
|
||||
if((offset+sizeof(o))>mData.size()) return false;
|
||||
memcpy(&o, &(mData.front())+offset, sizeof(o));
|
||||
if((offset+32)>mData.size()) return false;
|
||||
memcpy(&o, &(mData.front())+offset, 32);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint256 Serializer::get256(int offset) const
|
||||
{
|
||||
uint256 ret;
|
||||
if((offset+sizeof(ret))>mData.size()) return ret;
|
||||
memcpy(&ret, &(mData.front())+offset, sizeof(ret));
|
||||
if((offset+32)>mData.size()) return ret;
|
||||
memcpy(&ret, &(mData.front())+offset, 32);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,20 +26,20 @@ Transaction::Transaction(TransStatus status, LocalAccount& fromLocalAccount, uin
|
||||
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;
|
||||
if(s.getLength()<145) { assert(false); return; }
|
||||
if(!s.get160(mAccountTo, 0)) { assert(false); return; }
|
||||
if(!s.get64(mAmount, 20)) { assert(false); return; }
|
||||
if(!s.get32(mFromAccountSeq, 28)) { assert(false); return; }
|
||||
if(!s.get32(mSourceLedger, 32)) { assert(false); return; }
|
||||
if(!s.get32(mIdent, 36)) { assert(false); return; }
|
||||
if(!s.getRaw(mSignature, 69, 72)) { assert(false); return; }
|
||||
|
||||
std::vector<unsigned char> pubKey;
|
||||
if(!s.getRaw(pubKey, 40, 33)) return;
|
||||
if(!mFromPubKey.SetPubKey(pubKey)) return;
|
||||
if(!s.getRaw(pubKey, 40, 33)) { assert(false); return; }
|
||||
if(!mFromPubKey.SetPubKey(pubKey)) { assert(false); return; }
|
||||
updateID();
|
||||
|
||||
if(validate && !checkSign()) return;
|
||||
if(validate && !checkSign()) { assert(false); return; }
|
||||
|
||||
mStatus=NEW;
|
||||
}
|
||||
@@ -47,12 +47,23 @@ Transaction::Transaction(const std::vector<unsigned char> &t, bool validate) : m
|
||||
bool Transaction::sign(LocalAccount& fromLocalAccount)
|
||||
{
|
||||
if( (mAmount==0) || (mSourceLedger==0) || (mAccountTo==0) )
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
if(mAccountFrom!=fromLocalAccount.mAddress.GetHash160())
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
Serializer::pointer signBuf=getRaw(true);
|
||||
assert(signBuf->getLength()==73+4);
|
||||
if(!signBuf->makeSignature(mSignature, fromLocalAccount.peekPrivKey()))
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
assert(mSignature.size()==72);
|
||||
updateID();
|
||||
return true;
|
||||
}
|
||||
@@ -71,6 +82,7 @@ Serializer::pointer Transaction::getRaw(bool prefix) const
|
||||
{
|
||||
Serializer::pointer ret(new Serializer(77));
|
||||
if(prefix) ret->add32(0x54584e00u);
|
||||
ret->add160(mAccountTo);
|
||||
ret->addRaw(mFromPubKey.GetPubKey());
|
||||
ret->add64(mAmount);
|
||||
ret->add32(mFromAccountSeq);
|
||||
|
||||
@@ -18,13 +18,13 @@ We could have made something that inherited from the protobuf transaction but th
|
||||
|
||||
enum TransStatus
|
||||
{
|
||||
NEW, // just received / generated
|
||||
INVALID, // no valid signature, insufficient funds
|
||||
INCLUDED, // added to the current ledger
|
||||
CONFLICTED, // losing to a conflicting transaction
|
||||
COMMITTED, // known to be in a ledger
|
||||
HELD, // not valid now, maybe later
|
||||
REMOVED // taken out of a ledger
|
||||
NEW =0, // just received / generated
|
||||
INVALID =1, // no valid signature, insufficient funds
|
||||
INCLUDED =2, // added to the current ledger
|
||||
CONFLICTED =3, // losing to a conflicting transaction
|
||||
COMMITTED =4, // known to be in a ledger
|
||||
HELD =5, // not valid now, maybe later
|
||||
REMOVED =6 // taken out of a ledger
|
||||
};
|
||||
|
||||
class Account;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <string>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
LocalAccount::LocalAccount(bool)
|
||||
LocalAccount::LocalAccount(bool) : mAmount(0), mSeqNum(0)
|
||||
{
|
||||
mPrivateKey.MakeNewKey();
|
||||
mPublicKey.SetPubKey(mPrivateKey.GetPubKey());
|
||||
|
||||
17
key.h
17
key.h
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
@@ -176,10 +177,13 @@ public:
|
||||
unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
|
||||
CPrivKey vchPrivKey(nSize, 0);
|
||||
assert(nSize<=279);
|
||||
CPrivKey vchPrivKey(279, 0);
|
||||
unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
|
||||
assert(vchPrivKey.size()<=279);
|
||||
while(vchPrivKey.size()<279) vchPrivKey.push_back((unsigned char)0);
|
||||
return vchPrivKey;
|
||||
}
|
||||
|
||||
@@ -196,12 +200,15 @@ public:
|
||||
std::vector<unsigned char> GetPubKey() const
|
||||
{
|
||||
unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
|
||||
assert(nSize<=33);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
|
||||
std::vector<unsigned char> vchPubKey(nSize, 0);
|
||||
std::vector<unsigned char> vchPubKey(33, 0);
|
||||
unsigned char* pbegin = &vchPubKey[0];
|
||||
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
|
||||
assert(vchPubKey.size()<=33);
|
||||
while(vchPubKey.size()<33) vchPubKey.push_back((unsigned char)0);
|
||||
return vchPubKey;
|
||||
}
|
||||
|
||||
@@ -212,6 +219,12 @@ public:
|
||||
unsigned int nSize = 0;
|
||||
if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
|
||||
return false;
|
||||
while(nSize<72)
|
||||
{ // enlarge to 72 bytes
|
||||
pchSig[nSize]=0;
|
||||
nSize++;
|
||||
}
|
||||
assert(nSize==72);
|
||||
vchSig.resize(nSize);
|
||||
memcpy(&vchSig[0], pchSig, nSize);
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user