Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
Arthur Britto
2012-04-10 12:18:24 -07:00
22 changed files with 684 additions and 58 deletions

4
.gitignore vendored
View File

@@ -9,9 +9,13 @@
# Ignore python compiled files.
*.pyc
# Ignore backup/temps
*~
# Ignore object files.
*.o
obj/*
bin/newcoind
newcoind

6
bin/network-build Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh -x
cd ~/NewCoin
git pull
scons -j 2
cp -p newcoind bin/

10
bin/network-init Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/sh
# XXX Should not need to make db directory. newcoind should do this.
for SITE in $HOSTS
do
echo "Clearing db for:" $SITE
DB_DIR="/var/www/$SITE/db/"
mkdir -p "/var/www/$SITE/db/"
rm -rf "/var/www/$SITE/db/*"
done

5
bin/network-restart Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh -x
network-stop
sleep 1
network-start

6
bin/network-start Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
for SITE in $HOSTS
do
(nx $SITE &)
done

6
bin/network-stop Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
for SITE in $HOSTS
do
(nx $SITE stop &)
done

5
bin/network-update Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh -x
echo "Building and restarting."
network-build
network-restart

7
bin/nx Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
SITE=$1
shift
COMMAND=$@
cd "/var/www/$SITE"
newcoind $COMMAND

177
src/Amount.cpp Normal file
View File

@@ -0,0 +1,177 @@
#include <cmath>
#include <boost/lexical_cast.hpp>
#include "SerializedTypes.h"
void STAmount::canonicalize()
{
if(value==0)
{
offset=0;
value=0;
}
while(value<cMinValue)
{
if(offset<=cMinOffset) throw std::runtime_error("value overflow");
value*=10;
offset-=1;
}
while(value>cMaxValue)
{ // Here we can make it throw on precision loss if we wish: ((value%10)!=0)
if(offset>=cMaxOffset) throw std::runtime_error("value underflow");
value/=10;
offset+=1;
}
assert( (value==0) || ( (value>=cMinValue) && (value<=cMaxValue) ) );
assert( (offset>=cMinOffset) && (offset<=cMaxOffset) );
}
STAmount* STAmount::construct(SerializerIterator& sit, const char *name)
{
uint64 value = sit.get64();
int offset = static_cast<int>(value>>(64-8));
offset-=142;
value&=~(255ull<<(64-8));
if(value==0)
{
if(offset!=0)
throw std::runtime_error("invalid currency value");
}
else
{
if( (value<cMinValue) || (value>cMaxValue) || (offset<cMinOffset) || (offset>cMaxOffset) )
throw std::runtime_error("invalid currency value");
}
return new STAmount(name, value, offset);
}
std::string STAmount::getText() const
{
return boost::lexical_cast<std::string>(static_cast<double>(*this));
}
void STAmount::add(Serializer& s) const
{
uint64 v=value;
v+=(static_cast<uint64>(offset+142) << (64-8));
s.add64(v);
}
bool STAmount::isEquivalent(const SerializedType& t) const
{
const STAmount* v=dynamic_cast<const STAmount*>(&t);
if(!v) return false;
return (value==v->value) && (offset==v->offset);
}
bool STAmount::operator==(const STAmount& a) const
{
return (offset==a.offset) && (value==a.value);
}
bool STAmount::operator!=(const STAmount& a) const
{
return (offset!=a.offset) || (value!=a.value);
}
bool STAmount::operator<(const STAmount& a) const
{
if(offset<a.offset) return true;
if(a.offset<offset) return false;
return value < a.value;
}
bool STAmount::operator>(const STAmount& a) const
{
if(offset>a.offset) return true;
if(a.offset>offset) return false;
return value > a.value;
}
bool STAmount::operator<=(const STAmount& a) const
{
if(offset<a.offset) return true;
if(a.offset<offset) return false;
return value <= a.value;
}
bool STAmount::operator>=(const STAmount& a) const
{
if(offset>a.offset) return true;
if(a.offset>offset) return false;
return value >= a.value;
}
STAmount& STAmount::operator+=(const STAmount& a)
{
*this = *this + a;
return *this;
}
STAmount& STAmount::operator-=(const STAmount& a)
{
*this = *this - a;
return *this;
}
STAmount& STAmount::operator=(const STAmount& a)
{
value=a.value;
offset=a.offset;
return *this;
}
STAmount& STAmount::operator=(uint64 v)
{
return *this=STAmount(v, 0);
}
STAmount& STAmount::operator+=(uint64 v)
{
return *this+=STAmount(v);
}
STAmount& STAmount::operator-=(uint64 v)
{
return *this-=STAmount(v);
}
STAmount operator+(STAmount v1, STAmount v2)
{ // We can check for precision loss here (value%10)!=0
while(v1.offset < v2.offset)
{
v1.value/=10;
v1.offset+=1;
}
while(v2.offset < v1.offset)
{
v2.value/=10;
v2.offset+=1;
}
// this addition cannot overflow
return STAmount(v1.name, v1.value + v2.value, v1.offset);
}
STAmount operator-(STAmount v1, STAmount v2)
{ // We can check for precision loss here (value%10)!=0
while(v1.offset < v2.offset)
{
v1.value/=10;
v1.offset+=1;
}
while(v2.offset < v1.offset)
{
v2.value/=10;
v2.offset+=1;
}
if(v1.value < v2.value) throw std::runtime_error("value overflow");
return STAmount(v1.name, v1.value - v2.value, v1.offset);
}
STAmount::operator double() const
{
if(!value) return 0.0;
return static_cast<double>(value) * pow(10.0, offset);
}

56
src/Currency.cpp Normal file
View File

@@ -0,0 +1,56 @@
#include "Currency.h"
#include <cmath>
#include <stdexcept>
uint160 Currency::sNatMask("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000");
uint160 Currency::sNatZero("FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000");
uint64 Amount::sMaxCanon(1ull << 63);
Currency::Currency(const uint160& v) : mValue(v)
{
if (!v) mType = ctNATIVE;
if (!(v & sNatZero)) mType = ctNATIONAL;
mType = ctNATIONAL;
}
bool Currency::isCommensurate(const Currency& c) const
{
if (isNative())
return c.isNative();
if (isCustom())
return mValue == c.mValue;
if (!c.isNational()) return false;
return (mValue & sNatMask) == (c.mValue & sNatMask);
}
unsigned char Currency::getScale() const
{
return *(mValue.begin());
}
void Currency::setScale(unsigned char s)
{
*(mValue.begin()) = s;
}
void Amount::canonicalize()
{ // clear high bit to avoid overflows
if(mQuantity > sMaxCanon)
{
if (!mCurrency.isNational()) throw std::runtime_error("Currency overflow");
unsigned char s = mCurrency.getScale();
if (s==255) throw std::runtime_error("Currency overflow");
mCurrency.setScale(s + 1);
mQuantity /= 10.0;
}
}
double Amount::getDisplayQuantity() const
{
if(!mCurrency.isNational()) throw std::runtime_error("Can only scale national currencies");
int scale=mCurrency.getScale();
return static_cast<double>(mQuantity) * pow(10, 128-scale);
}

80
src/Currency.h Normal file
View File

@@ -0,0 +1,80 @@
#ifndef __CURRENCY__
#define __CURRENCY__
#include <string>
#include "uint256.h"
enum CurrencyType
{
ctNATIVE, // Currency transaction fees are paid in
ctNATIONAL, // State-issued or ISO-recognized currencies
ctCUSTOM, // Custom currencies
};
class Currency
{
protected:
uint160 mValue;
CurrencyType mType;
static uint160 sNatMask; // bits that indicate national currency ISO code and version
static uint160 sNatZero; // bits that must be zero on a national currency
public:
Currency() : mType(ctNATIVE) { ; }
Currency(const uint160& v);
Currency(const std::string& iso, uint16 version, unsigned char scale);
bool isCommensurate(const Currency&) const;
bool isNational() const { return mType == ctNATIONAL; }
bool isNative() const { return mType == ctNATIVE; }
bool isCustom() const { return mType == ctCUSTOM; }
const uint160& getCurrency() { return mValue; }
unsigned char getScale() const;
void setScale(unsigned char c);
// These are only valid for national currencies
std::string getISO() const;
uint16 getVersion() const;
};
class Amount
{
// CAUTION: Currency operations throw on overflows, underflos, or
// incommensurate currency opeations (like adding USD to Euros)
protected:
Currency mCurrency;
uint64 mQuantity;
void canonicalize();
static uint64 sMaxCanon; // Max native currency value before shift
public:
Amount(const Currency& c, const uint64& q) : mCurrency(c), mQuantity(q) { canonicalize(); }
const Currency& getCurrency() const { return mCurrency; }
uint64 getQuantity() const { return mQuantity; }
double getDisplayQuantity() const;
// These throw if the currencies are incommensurate
// They handle scaling and represent the result as accurately as possible
bool operator==(const Amount&) const;
bool operator!=(const Amount&) const;
bool operator>=(const Amount&) const;
bool operator<=(const Amount&) const;
bool operator>(const Amount&) const;
bool operator<(const Amount&) const;
Amount& operator+=(const Amount& a) { return *this = *this + a; }
Amount& operator-=(const Amount& a) { return *this = *this - a; }
// This is used to score offers and works with incommensurate currencies
friend void divide(const Amount& offering, const Amount& taking, uint16& exponent, uint64& mantissa);
friend Amount& operator+(const Amount&, const Amount&);
friend Amount& operator-(const Amount&, const Amount&);
};
#endif

View File

@@ -32,6 +32,9 @@
// 3) Encrypted: Original plaintext
// 4) Encrypted: Rest of block/padding
// ECIES operations throw on any error such as a corrupt message or incorrect
// key. They *must* be called in try/catch blocks.
// Algorithmic choices:
#define ECIES_KEY_HASH SHA512 // Hash used to expand shared secret
#define ECIES_KEY_LENGTH (512/8) // Size of expanded shared secret

View File

@@ -9,7 +9,7 @@ LedgerEntryFormat LedgerFormats[]=
{ S_FIELD(Flags), STI_UINT16, SOE_FLAGS, 0 },
{ S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Sequence), STI_UINT32, SOE_REQUIRED, 0 },
{ S_FIELD(Balance), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(LastReceive), STI_UINT32, SOE_REQUIRED, 0 },
{ S_FIELD(LastTxn), STI_UINT32, SOE_REQUIRED, 0 },
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 1 },
@@ -23,8 +23,8 @@ LedgerEntryFormat LedgerFormats[]=
{ S_FIELD(Borrower), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Lender), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Currency), STI_HASH160, SOE_IFFLAG, 1 },
{ S_FIELD(Limit), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(Balance), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(Limit), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(CurrentRate), STI_UINT32, SOE_IFFLAG, 2 },
{ S_FIELD(RateLock), STI_UINT32, SOE_IFFLAG, 4 },
{ S_FIELD(NextRate), STI_UINT32, SOE_IFFLAG, 8 },
@@ -37,7 +37,7 @@ LedgerEntryFormat LedgerFormats[]=
{ S_FIELD(Flags), STI_UINT16, SOE_FLAGS, 0 },
{ S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 },
{ S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(MinimumOffer), STI_UINT64, SOE_IFFLAG, 1 },
{ S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 },
{ S_FIELD(OfferCurrency),STI_HASH160, SOE_IFFLAG, 2 },
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 32768 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }

View File

@@ -1,3 +1,52 @@
#include "SerializedLedger.h"
SerializedLedger::SerializedLedger(SerializerIterator& sit, const uint256& index)
: STObject("LedgerEntry"), mIndex(index)
{
uint16 type=sit.get16();
mFormat=getLgrFormat(static_cast<LedgerEntryType>(type));
if(mFormat==NULL) throw std::runtime_error("invalid ledger entry type");
mType=mFormat->t_type;
mVersion.setValue(type);
mObject=STObject(mFormat->elements, sit, "Entry");
}
SerializedLedger::SerializedLedger(LedgerEntryType type) : STObject("LedgerEntry"), mType(type)
{
mFormat=getLgrFormat(type);
if(mFormat==NULL) throw std::runtime_error("invalid ledger entry type");
mVersion.setValue(static_cast<uint16>(mFormat->t_type));
mObject=STObject(mFormat->elements, "Entry");
}
std::string SerializedLedger::getFullText() const
{
std::string ret="\"";
ret+=mIndex.GetHex();
ret+="\" = { ";
ret+=mFormat->t_name;
ret+=", ";
ret+=mObject.getFullText();
ret+="}";
return ret;
}
std::string SerializedLedger::getText() const
{
std::string ret="{";
ret+=mIndex.GetHex();
ret+=mVersion.getText();
ret+=mObject.getText();
ret+="}";
return ret;
}
bool SerializedLedger::isEquivalent(const SerializedType& t) const
{ // locators are not compared
const SerializedLedger* v=dynamic_cast<const SerializedLedger*>(&t);
if(!v) return false;
if(mType != v->mType) return false;
if(mObject != v->mObject) return false;
return true;
}

View File

@@ -10,21 +10,59 @@ public:
typedef boost::shared_ptr<SerializedLedger> pointer;
protected:
uint256 mIndex;
LedgerEntryType mType;
STUInt16 mVersion;
STObject mObject;
LedgerEntryFormat* mFormat;
public:
SerializedLedger(SerializerIterator& sit);
SerializedLedger(SerializerIterator& sit, const uint256& index);
SerializedLedger(LedgerEntryType type);
int getLength() const { return mVersion.getLength() + mObject.getLength(); }
SerializedTypeID getType() const { return STI_LEDGERENTRY; }
SerializedLedger* duplicate() const { return new SerializedLedger(*this); }
std::string getFullText() const;
std::string getText() const;
void add(Serializer& s) const { mVersion.add(s); mObject.add(s); }
SerializedTypeID getSType() const { return STI_LEDGERENTRY; }
SerializedLedger* duplicate() const { return new SerializedLedger(*this); }
std::string getFullText() const;
std::string getText() const;
void add(Serializer& s) const { mVersion.add(s); mObject.add(s); }
virtual bool isEquivalent(const SerializedType& t) const;
const uint256& getIndex() const { return mIndex; }
void setIndex(const uint256& i) { mIndex=i; }
LedgerEntryType getType() const { return mType; }
uint16 getVersion() const { return mVersion.getValue(); }
LedgerEntryFormat* getFormat() { return mFormat; }
int getIFieldIndex(SOE_Field field) const { return mObject.getFieldIndex(field); }
int getIFieldCount() const { return mObject.getCount(); }
const SerializedType& peekIField(SOE_Field field) const { return mObject.peekAtField(field); }
SerializedType& getIField(SOE_Field field) { return mObject.getField(field); }
std::string getIFieldString(SOE_Field field) const { return mObject.getFieldString(field); }
unsigned char getIFieldU8(SOE_Field field) const { return mObject.getValueFieldU8(field); }
uint16 getIFieldU16(SOE_Field field) const { return mObject.getValueFieldU16(field); }
uint32 getIFieldU32(SOE_Field field) const { return mObject.getValueFieldU32(field); }
uint64 getIFieldU64(SOE_Field field) const { return mObject.getValueFieldU64(field); }
uint160 getIFieldH160(SOE_Field field) const { return mObject.getValueFieldH160(field); }
uint256 getIFieldH256(SOE_Field field) const { return mObject.getValueFieldH256(field); }
std::vector<unsigned char> getIFieldVL(SOE_Field field) const { return mObject.getValueFieldVL(field); }
std::vector<TaggedListItem> getIFieldTL(SOE_Field field) const { return mObject.getValueFieldTL(field); }
void setIFieldU8(SOE_Field field, unsigned char v) { return mObject.setValueFieldU8(field, v); }
void setIFieldU16(SOE_Field field, uint16 v) { return mObject.setValueFieldU16(field, v); }
void setIFieldU32(SOE_Field field, uint32 v) { return mObject.setValueFieldU32(field, v); }
void setIFieldU64(SOE_Field field, uint32 v) { return mObject.setValueFieldU64(field, v); }
void setIFieldH160(SOE_Field field, const uint160& v) { return mObject.setValueFieldH160(field, v); }
void setIFieldH256(SOE_Field field, const uint256& v) { return mObject.setValueFieldH256(field, v); }
void setIFieldVL(SOE_Field field, const std::vector<unsigned char>& v)
{ return mObject.setValueFieldVL(field, v); }
void setIFieldTL(SOE_Field field, const std::vector<TaggedListItem>& v)
{ return mObject.setValueFieldTL(field, v); }
bool getIFieldPresent(SOE_Field field) const { return mObject.isFieldPresent(field); }
void makeIFieldPresent(SOE_Field field) { return mObject.makeFieldPresent(field); }
void makeIFieldAbsent(SOE_Field field) { return mObject.makeFieldAbsent(field); }
};

View File

@@ -16,6 +16,9 @@ SerializedType* STObject::makeDefaultObject(SerializedTypeID id, const char *nam
case STI_UINT64:
return new STUInt64(name);
case STI_AMOUNT:
return new STAmount(name);
case STI_HASH160:
return new STHash160(name);
@@ -49,6 +52,9 @@ SerializedType* STObject::makeDeserializedObject(SerializedTypeID id, const char
case STI_UINT64:
return STUInt64::construct(sit, name);
case STI_AMOUNT:
return STAmount::construct(sit, name);
case STI_HASH160:
return STHash160::construct(sit, name);
@@ -167,6 +173,22 @@ std::string STObject::getText() const
return ret;
}
bool STObject::isEquivalent(const SerializedType& t) const
{
const STObject* v=dynamic_cast<const STObject*>(&t);
if(!v) return false;
boost::ptr_vector<SerializedType>::const_iterator it1=mData.begin(), end1=mData.end();
boost::ptr_vector<SerializedType>::const_iterator it2=v->mData.begin(), end2=v->mData.end();
while((it1!=end1) && (it2!=end2))
{
if(it1->getSType() != it2->getSType()) return false;
if(!it1->isEquivalent(*it2)) return false;
++it1;
++it2;
}
return (it1==end1) && (it2==end2);
}
int STObject::getFieldIndex(SOE_Field field) const
{
int i=0;
@@ -207,7 +229,7 @@ bool STObject::isFieldPresent(SOE_Field field) const
{
int index=getFieldIndex(field);
if(index==-1) return false;
return peekAtIndex(field).getType()==STI_OBJECT;
return peekAtIndex(field).getSType()==STI_OBJECT;
}
bool STObject::setFlag(int f)
@@ -240,7 +262,7 @@ void STObject::makeFieldPresent(SOE_Field field)
{
int index=getFieldIndex(field);
if(index==-1) throw std::runtime_error("Field not found");
if(peekAtIndex(field).getType()!=STI_OBJECT) return;
if(peekAtIndex(field).getSType()!=STI_OBJECT) return;
mData.replace(index, makeDefaultObject(mType[index]->e_id, mType[index]->e_name));
setFlag(mType[index]->e_flags);
}
@@ -249,7 +271,7 @@ void STObject::makeFieldAbsent(SOE_Field field)
{
int index=getFieldIndex(field);
if(index==-1) throw std::runtime_error("Field not found");
if(peekAtIndex(field).getType()==STI_OBJECT) return;
if(peekAtIndex(field).getSType()==STI_OBJECT) return;
mData.replace(index, new STObject(mType[index]->e_name));
clearFlag(mType[index]->e_flags);
}
@@ -265,7 +287,7 @@ unsigned char STObject::getValueFieldU8(SOE_Field field) const
{
const SerializedType* rf=peekAtPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT) return 0; // optional field not present
const STUInt8 *cf=dynamic_cast<const STUInt8 *>(rf);
if(!cf) throw std::runtime_error("Wrong field type");
@@ -276,7 +298,7 @@ uint16 STObject::getValueFieldU16(SOE_Field field) const
{
const SerializedType* rf=peekAtPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT) return 0; // optional field not present
const STUInt16 *cf=dynamic_cast<const STUInt16 *>(rf);
if(!cf) throw std::runtime_error("Wrong field type");
@@ -287,7 +309,7 @@ uint32 STObject::getValueFieldU32(SOE_Field field) const
{
const SerializedType* rf=peekAtPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT) return 0; // optional field not present
const STUInt32 *cf=dynamic_cast<const STUInt32 *>(rf);
if(!cf) throw std::runtime_error("Wrong field type");
@@ -298,7 +320,7 @@ uint64 STObject::getValueFieldU64(SOE_Field field) const
{
const SerializedType* rf=peekAtPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT) return 0; // optional field not present
const STUInt64 *cf=dynamic_cast<const STUInt64 *>(rf);
if(!cf) throw std::runtime_error("Wrong field type");
@@ -309,7 +331,7 @@ uint160 STObject::getValueFieldH160(SOE_Field field) const
{
const SerializedType* rf=peekAtPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT) return uint160(); // optional field not present
const STHash160 *cf=dynamic_cast<const STHash160 *>(rf);
if(!cf) throw std::runtime_error("Wrong field type");
@@ -320,7 +342,7 @@ uint256 STObject::getValueFieldH256(SOE_Field field) const
{
const SerializedType* rf=peekAtPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT) return uint256(); // optional field not present
const STHash256 *cf=dynamic_cast<const STHash256 *>(rf);
if(!cf) throw std::runtime_error("Wrong field type");
@@ -331,7 +353,7 @@ std::vector<unsigned char> STObject::getValueFieldVL(SOE_Field field) const
{
const SerializedType* rf=peekAtPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT) return std::vector<unsigned char>(); // optional field not present
const STVariableLength *cf=dynamic_cast<const STVariableLength *>(rf);
if(!cf) throw std::runtime_error("Wrong field type");
@@ -342,7 +364,7 @@ std::vector<TaggedListItem> STObject::getValueFieldTL(SOE_Field field) const
{
const SerializedType* rf=peekAtPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT) return std::vector<TaggedListItem>(); // optional field not present
const STTaggedList *cf=dynamic_cast<const STTaggedList *>(rf);
if(!cf) throw std::runtime_error("Wrong field type");
@@ -353,12 +375,12 @@ void STObject::setValueFieldU8(SOE_Field field, unsigned char v)
{
SerializedType* rf=getPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT)
{
makeFieldPresent(field);
rf=getPField(field);
id=rf->getType();
id=rf->getSType();
}
STUInt8* cf=dynamic_cast<STUInt8*>(rf);
if(!cf) throw(std::runtime_error("Wrong field type"));
@@ -369,12 +391,12 @@ void STObject::setValueFieldU16(SOE_Field field, uint16 v)
{
SerializedType* rf=getPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT)
{
makeFieldPresent(field);
rf=getPField(field);
id=rf->getType();
id=rf->getSType();
}
STUInt16* cf=dynamic_cast<STUInt16*>(rf);
if(!cf) throw(std::runtime_error("Wrong field type"));
@@ -385,12 +407,12 @@ void STObject::setValueFieldU32(SOE_Field field, uint32 v)
{
SerializedType* rf=getPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT)
{
makeFieldPresent(field);
rf=getPField(field);
id=rf->getType();
id=rf->getSType();
}
STUInt32* cf=dynamic_cast<STUInt32*>(rf);
if(!cf) throw(std::runtime_error("Wrong field type"));
@@ -401,12 +423,12 @@ void STObject::setValueFieldU64(SOE_Field field, uint64 v)
{
SerializedType* rf=getPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT)
{
makeFieldPresent(field);
rf=getPField(field);
id=rf->getType();
id=rf->getSType();
}
STUInt64* cf=dynamic_cast<STUInt64*>(rf);
if(!cf) throw(std::runtime_error("Wrong field type"));
@@ -417,12 +439,12 @@ void STObject::setValueFieldH160(SOE_Field field, const uint160& v)
{
SerializedType* rf=getPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT)
{
makeFieldPresent(field);
rf=getPField(field);
id=rf->getType();
id=rf->getSType();
}
STHash160* cf=dynamic_cast<STHash160*>(rf);
if(!cf) throw(std::runtime_error("Wrong field type"));
@@ -433,12 +455,12 @@ void STObject::setValueFieldVL(SOE_Field field, const std::vector<unsigned char>
{
SerializedType* rf=getPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT)
{
makeFieldPresent(field);
rf=getPField(field);
id=rf->getType();
id=rf->getSType();
}
STVariableLength* cf=dynamic_cast<STVariableLength*>(rf);
if(!cf) throw(std::runtime_error("Wrong field type"));
@@ -449,12 +471,12 @@ void STObject::setValueFieldTL(SOE_Field field, const std::vector<TaggedListItem
{
SerializedType* rf=getPField(field);
if(!rf) throw std::runtime_error("Field not found");
SerializedTypeID id=rf->getType();
SerializedTypeID id=rf->getSType();
if(id==STI_OBJECT)
{
makeFieldPresent(field);
rf=getPField(field);
id=rf->getType();
id=rf->getSType();
}
STTaggedList* cf=dynamic_cast<STTaggedList*>(rf);
if(!cf) throw(std::runtime_error("Wrong field type"));
@@ -467,7 +489,7 @@ Json::Value STObject::getJson(int options) const
int index=1;
for(boost::ptr_vector<SerializedType>::const_iterator it=mData.begin(), end=mData.end(); it!=end; ++it, ++index)
{
if(it->getType()!=STI_NOTPRESENT)
if(it->getSType()!=STI_NOTPRESENT)
{
if(it->getName()==NULL)
ret[boost::lexical_cast<std::string>(index)]=it->getText();

View File

@@ -56,8 +56,9 @@ public:
virtual ~STObject() { ; }
int getLength() const;
SerializedTypeID getType() const { return STI_OBJECT; }
SerializedTypeID getSType() const { return STI_OBJECT; }
STObject* duplicate() const { return new STObject(*this); }
virtual bool isEquivalent(const SerializedType& t) const;
void add(Serializer& s) const;
std::string getFullText() const;

View File

@@ -77,6 +77,16 @@ int SerializedTransaction::getTransaction(Serializer& s, bool include_length) co
return l;
}
bool SerializedTransaction::isEquivalent(const SerializedType& t) const
{ // Signatures are not compared
const SerializedTransaction* v=dynamic_cast<const SerializedTransaction*>(&t);
if(!v) return false;
if(type != v->type) return false;
if(mMiddleTxn != v->mMiddleTxn) return false;
if(mInnerTxn != v->mInnerTxn) return false;
return true;
}
uint256 SerializedTransaction::getSigningHash() const
{
Serializer s;
@@ -206,7 +216,7 @@ bool SerializedTransaction::getITFieldPresent(SOE_Field field) const
return mInnerTxn.isFieldPresent(field);
}
const SerializedType& SerializedTransaction::peekITField(SOE_Field field)
const SerializedType& SerializedTransaction::peekITField(SOE_Field field) const
{
return mInnerTxn.peekAtField(field);
}

View File

@@ -26,11 +26,12 @@ public:
// STObject functions
int getLength() const;
SerializedTypeID getType() const { return STI_TRANSACTION; }
SerializedTypeID getSType() const { return STI_TRANSACTION; }
SerializedTransaction* duplicate() const { return new SerializedTransaction(*this); }
std::string getFullText() const;
std::string getText() const;
void add(Serializer& s) const { getTransaction(s, true); }
virtual bool isEquivalent(const SerializedType& t) const;
// outer transaction functions / signature functions
std::vector<unsigned char> getSignature() const;
@@ -62,7 +63,7 @@ public:
// inner transaction field functions
int getITFieldIndex(SOE_Field field) const;
int getITFieldCount() const;
const SerializedType& peekITField(SOE_Field field);
const SerializedType& peekITField(SOE_Field field) const;
SerializedType& getITField(SOE_Field field);
// inner transaction field value functions

View File

@@ -9,7 +9,7 @@
std::string SerializedType::getFullText() const
{
std::string ret;
if(getType()!=STI_NOTPRESENT)
if(getSType()!=STI_NOTPRESENT)
{
if(name!=NULL)
{
@@ -31,6 +31,12 @@ std::string STUInt8::getText() const
return boost::lexical_cast<std::string>(value);
}
bool STUInt8::isEquivalent(const SerializedType& t) const
{
const STUInt8* v=dynamic_cast<const STUInt8*>(&t);
return v && (value==v->value);
}
STUInt16* STUInt16::construct(SerializerIterator& u, const char *name)
{
return new STUInt16(name, u.get16());
@@ -41,8 +47,14 @@ std::string STUInt16::getText() const
return boost::lexical_cast<std::string>(value);
}
STUInt32* STUInt32::construct(SerializerIterator& u, const char *name)
bool STUInt16::isEquivalent(const SerializedType& t) const
{
const STUInt16* v=dynamic_cast<const STUInt16*>(&t);
return v && (value==v->value);
}
STUInt32* STUInt32::construct(SerializerIterator& u, const char *name)
{
return new STUInt32(name, u.get32());
}
@@ -51,6 +63,12 @@ std::string STUInt32::getText() const
return boost::lexical_cast<std::string>(value);
}
bool STUInt32::isEquivalent(const SerializedType& t) const
{
const STUInt32* v=dynamic_cast<const STUInt32*>(&t);
return v && (value==v->value);
}
STUInt64* STUInt64::construct(SerializerIterator& u, const char *name)
{
return new STUInt64(name, u.get64());
@@ -61,6 +79,12 @@ std::string STUInt64::getText() const
return boost::lexical_cast<std::string>(value);
}
bool STUInt64::isEquivalent(const SerializedType& t) const
{
const STUInt64* v=dynamic_cast<const STUInt64*>(&t);
return v && (value==v->value);
}
STHash128* STHash128::construct(SerializerIterator& u, const char *name)
{
return new STHash128(name, u.get128());
@@ -71,6 +95,12 @@ std::string STHash128::getText() const
return value.GetHex();
}
bool STHash128::isEquivalent(const SerializedType& t) const
{
const STHash128* v=dynamic_cast<const STHash128*>(&t);
return v && (value==v->value);
}
STHash160* STHash160::construct(SerializerIterator& u, const char *name)
{
return new STHash160(name, u.get160());
@@ -81,6 +111,12 @@ std::string STHash160::getText() const
return value.GetHex();
}
bool STHash160::isEquivalent(const SerializedType& t) const
{
const STHash160* v=dynamic_cast<const STHash160*>(&t);
return v && (value==v->value);
}
STHash256* STHash256::construct(SerializerIterator& u, const char *name)
{
return new STHash256(name, u.get256());
@@ -91,6 +127,12 @@ std::string STHash256::getText() const
return value.GetHex();
}
bool STHash256::isEquivalent(const SerializedType& t) const
{
const STHash256* v=dynamic_cast<const STHash256*>(&t);
return v && (value==v->value);
}
static std::string hex(const std::vector<unsigned char>& value)
{
int dlen=value.size(), i=0;
@@ -115,6 +157,12 @@ int STVariableLength::getLength() const
return Serializer::encodeLengthLength(value.size()) + value.size();
}
bool STVariableLength::isEquivalent(const SerializedType& t) const
{
const STVariableLength* v=dynamic_cast<const STVariableLength*>(&t);
return v && (value==v->value);
}
std::string STAccount::getText() const
{
uint160 u;
@@ -177,4 +225,8 @@ int STTaggedList::getLength() const
return ret;
}
bool STTaggedList::isEquivalent(const SerializedType& t) const
{
const STTaggedList* v=dynamic_cast<const STTaggedList*>(&t);
return v && (value==v->value);
}

View File

@@ -15,6 +15,7 @@ enum SerializedTypeID
// standard types
STI_OBJECT=1, STI_UINT8=2, STI_UINT16=3, STI_UINT32=4, STI_UINT64=5,
STI_HASH128=6, STI_HASH160=7, STI_HASH256=8, STI_VL=9, STI_TL=10,
STI_AMOUNT=11,
// high level types
STI_ACCOUNT=100, STI_TRANSACTION=101, STI_LEDGERENTRY=102
@@ -29,13 +30,14 @@ public:
SerializedType() : name(NULL) { ; }
SerializedType(const char *n) : name(n) { ; }
SerializedType(const SerializedType& n) : name(n.name) { ; }
virtual ~SerializedType() { ; }
void setName(const char *n) { name=n; }
const char *getName() const { return name; }
virtual int getLength() const { return 0; }
virtual SerializedTypeID getType() const { return STI_NOTPRESENT; }
virtual SerializedTypeID getSType() const { return STI_NOTPRESENT; }
virtual SerializedType* duplicate() const { return new SerializedType(name); }
virtual std::string getFullText() const;
@@ -46,6 +48,13 @@ public:
SerializedType* new_clone(const SerializedType& s) { return s.duplicate(); }
void delete_clone(const SerializedType* s) { boost::checked_delete(s); }
virtual bool isEquivalent(const SerializedType& t) const { return true; }
bool operator==(const SerializedType& t) const
{ return (getSType()==t.getSType()) && isEquivalent(t); }
bool operator!=(const SerializedType& t) const
{ return (getSType()!=t.getSType()) || !isEquivalent(t); }
};
class STUInt8 : public SerializedType
@@ -60,7 +69,7 @@ public:
static STUInt8* construct(SerializerIterator&, const char *name=NULL);
int getLength() const { return 1; }
SerializedTypeID getType() const { return STI_UINT8; }
SerializedTypeID getSType() const { return STI_UINT8; }
STUInt8* duplicate() const { return new STUInt8(name, value); }
std::string getText() const;
void add(Serializer& s) const { s.add8(value); }
@@ -70,6 +79,7 @@ public:
operator unsigned char() const { return value; }
STUInt8& operator=(unsigned char v) { value=v; return *this; }
virtual bool isEquivalent(const SerializedType& t) const;
};
class STUInt16 : public SerializedType
@@ -84,7 +94,7 @@ public:
static STUInt16* construct(SerializerIterator&, const char *name=NULL);
int getLength() const { return 2; }
SerializedTypeID getType() const { return STI_UINT16; }
SerializedTypeID getSType() const { return STI_UINT16; }
STUInt16* duplicate() const { return new STUInt16(name, value); }
std::string getText() const;
void add(Serializer& s) const { s.add16(value); }
@@ -94,6 +104,7 @@ public:
operator uint16() const { return value; }
STUInt16& operator=(uint16 v) { value=v; return *this; }
virtual bool isEquivalent(const SerializedType& t) const;
};
class STUInt32 : public SerializedType
@@ -108,7 +119,7 @@ public:
static STUInt32* construct(SerializerIterator&, const char *name=NULL);
int getLength() const { return 4; }
SerializedTypeID getType() const { return STI_UINT32; }
SerializedTypeID getSType() const { return STI_UINT32; }
STUInt32* duplicate() const { return new STUInt32(name, value); }
std::string getText() const;
void add(Serializer& s) const { s.add32(value); }
@@ -118,6 +129,7 @@ public:
operator uint32() const { return value; }
STUInt32& operator=(uint32 v) { value=v; return *this; }
virtual bool isEquivalent(const SerializedType& t) const;
};
class STUInt64 : public SerializedType
@@ -132,7 +144,7 @@ public:
static STUInt64* construct(SerializerIterator&, const char *name=NULL);
int getLength() const { return 8; }
SerializedTypeID getType() const { return STI_UINT64; }
SerializedTypeID getSType() const { return STI_UINT64; }
STUInt64* duplicate() const { return new STUInt64(name, value); }
std::string getText() const;
void add(Serializer& s) const { s.add64(value); }
@@ -142,6 +154,77 @@ public:
operator uint64() const { return value; }
STUInt64& operator=(uint64 v) { value=v; return *this; }
virtual bool isEquivalent(const SerializedType& t) const;
};
class STAmount : public SerializedType
{
// Internal form:
// 1: If amount is zero, then offset and value are both zero.
// 2: Otherwise:
// legal offset range is -96 to +80 inclusive
// value range is 10^15 to (10^16 - 1) inclusive
// amount = value * [10 ^ offset]
// Wire form:
// High 8 bits are (offset+142), legal range is, 80 to 22 inclusive
// Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive
protected:
int offset; // These variables *always* hold canonical values on entry/exit
uint64 value;
void canonicalize();
static const int cMinOffset=-96, cMaxOffset=80;
static const uint64 cMinValue=1000000000000000ull, cMaxValue=9999999999999999ull;
public:
STAmount(uint64 v=0, int off=0) : offset(off), value(v)
{ canonicalize(); } // (1,0)=$1 (1,-2)=$.01 (100,0)=(10000,-2)=$.01
STAmount(const char *n, uint64 v=0, int off=1) : SerializedType(n), offset(off), value(v)
{ canonicalize(); }
STAmount(const STAmount& a) : SerializedType(a), offset(a.offset), value(a.value) { ; }
static STAmount* construct(SerializerIterator&, const char *name=NULL);
int getLength() const { return 8; }
SerializedTypeID getSType() const { return STI_AMOUNT; }
STAmount* duplicate() const { return new STAmount(name, offset, value); }
std::string getText() const;
void add(Serializer& s) const;
int getOffset() const { return offset; }
uint64 getValue() const { return value; }
virtual bool isEquivalent(const SerializedType& t) const;
bool operator==(const STAmount&) const;
bool operator!=(const STAmount&) const;
bool operator<(const STAmount&) const;
bool operator>(const STAmount&) const;
bool operator<=(const STAmount&) const;
bool operator>=(const STAmount&) const;
STAmount& operator+=(const STAmount&);
STAmount& operator-=(const STAmount&);
STAmount& operator=(const STAmount&);
STAmount& operator+=(uint64);
STAmount& operator-=(uint64);
STAmount& operator=(uint64);
operator double() const;
friend STAmount operator+(STAmount v1, STAmount v2);
friend STAmount operator-(STAmount v1, STAmount v2);
// Someone is offering X for Y, what is the rate?
friend STAmount getRate(const STAmount& offerIn, const STAmount& offerOut);
// Someone is offering X for Y, I pay Z, how much do I get?
friend STAmount getClaimed(const STAmount& offerIn, const STAmount& offerOut, const STAmount& paid);
// Someone is offering X for Y, I need Z, how much do I pay
friend STAmount getNeeded(const STAmount& offerIn, const STAmount& offerOut, const STAmount& needed);
};
class STHash128 : public SerializedType
@@ -157,7 +240,7 @@ public:
static STHash128* construct(SerializerIterator&, const char *name=NULL);
int getLength() const { return 20; }
SerializedTypeID getType() const { return STI_HASH128; }
SerializedTypeID getSType() const { return STI_HASH128; }
STHash128* duplicate() const { return new STHash128(name, value); }
virtual std::string getText() const;
void add(Serializer& s) const { s.add128(value); }
@@ -167,6 +250,7 @@ public:
operator uint128() const { return value; }
STHash128& operator=(const uint128& v) { value=v; return *this; }
virtual bool isEquivalent(const SerializedType& t) const;
};
class STHash160 : public SerializedType
@@ -182,7 +266,7 @@ public:
static STHash160* construct(SerializerIterator&, const char *name=NULL);
int getLength() const { return 20; }
SerializedTypeID getType() const { return STI_HASH160; }
SerializedTypeID getSType() const { return STI_HASH160; }
STHash160* duplicate() const { return new STHash160(name, value); }
virtual std::string getText() const;
void add(Serializer& s) const { s.add160(value); }
@@ -192,6 +276,7 @@ public:
operator uint160() const { return value; }
STHash160& operator=(const uint160& v) { value=v; return *this; }
virtual bool isEquivalent(const SerializedType& t) const;
};
class STHash256 : public SerializedType
@@ -207,7 +292,7 @@ public:
static STHash256* construct(SerializerIterator&, const char *name=NULL);
int getLength() const { return 32; }
SerializedTypeID getType() const { return STI_HASH256; }
SerializedTypeID getSType() const { return STI_HASH256; }
STHash256* duplicate() const { return new STHash256(name, value); }
std::string getText() const;
void add(Serializer& s) const { s.add256(value); }
@@ -217,6 +302,7 @@ public:
operator uint256() const { return value; }
STHash256& operator=(const uint256& v) { value=v; return *this; }
virtual bool isEquivalent(const SerializedType& t) const;
};
class STVariableLength : public SerializedType
@@ -233,7 +319,7 @@ public:
static STVariableLength* construct(SerializerIterator&, const char *name=NULL);
int getLength() const;
virtual SerializedTypeID getType() const { return STI_VL; }
virtual SerializedTypeID getSType() const { return STI_VL; }
virtual STVariableLength* duplicate() const { return new STVariableLength(name, value); }
virtual std::string getText() const;
void add(Serializer& s) const { s.addVL(value); }
@@ -245,6 +331,7 @@ public:
operator std::vector<unsigned char>() const { return value; }
STVariableLength& operator=(const std::vector<unsigned char>& v) { value=v; return *this; }
virtual bool isEquivalent(const SerializedType& t) const;
};
class STAccount : public STVariableLength
@@ -257,7 +344,7 @@ public:
STAccount() { ; }
static STAccount* construct(SerializerIterator&, const char *name=NULL);
SerializedTypeID getType() const { return STI_ACCOUNT; }
SerializedTypeID getSType() const { return STI_ACCOUNT; }
virtual STAccount* duplicate() const { return new STAccount(name, value); }
std::string getText() const;
@@ -280,7 +367,7 @@ public:
static STTaggedList* construct(SerializerIterator&, const char *name=NULL);
int getLength() const;
SerializedTypeID getType() const { return STI_TL; }
SerializedTypeID getSType() const { return STI_TL; }
STTaggedList* duplicate() const { return new STTaggedList(name, value); }
std::string getText() const;
void add(Serializer& s) const { if(s.addTaggedList(value)<0) throw(0); }
@@ -299,6 +386,7 @@ public:
operator std::vector<TaggedListItem>() const { return value; }
STTaggedList& operator=(const std::vector<TaggedListItem>& v) { value=v; return *this; }
virtual bool isEquivalent(const SerializedType& t) const;
};
#endif

View File

@@ -8,7 +8,7 @@ TransactionFormat InnerTxnFormats[]=
{ "MakePayment", ttMAKE_PAYMENT, {
{ S_FIELD(Flags), STI_UINT16, SOE_FLAGS, 0 },
{ S_FIELD(Destination), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Amount), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Currency), STI_HASH160, SOE_IFFLAG, 1 },
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 2 },
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 4 },
@@ -19,7 +19,7 @@ TransactionFormat InnerTxnFormats[]=
{ "Invoice", ttINVOICE, {
{ S_FIELD(Flags), STI_UINT16, SOE_FLAGS, 0 },
{ S_FIELD(Target), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Amount), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Currency), STI_HASH160, SOE_IFFLAG, 1 },
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 2 },
{ S_FIELD(Destination), STI_ACCOUNT, SOE_IFFLAG, 4 },
@@ -30,9 +30,9 @@ TransactionFormat InnerTxnFormats[]=
},
{ "Offer", ttEXCHANGE_OFFER, {
{ S_FIELD(Flags), STI_UINT16, SOE_FLAGS, 0 },
{ S_FIELD(AmountIn), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(AmountIn), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(CurrencyIn), STI_HASH160, SOE_IFFLAG, 2 },
{ S_FIELD(AmountOut), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(AmountOut), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(CurrencyOut), STI_HASH160, SOE_IFFLAG, 4 },
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 8 },
{ S_FIELD(Destination), STI_ACCOUNT, SOE_IFFLAG, 16 },