mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Move ./modules to ./src
This commit is contained in:
215
src/ripple_data/protocol/BuildInfo.cpp
Normal file
215
src/ripple_data/protocol/BuildInfo.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
char const* BuildInfo::getRawVersionString ()
|
||||
{
|
||||
static char const* const rawText =
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// The build version number (edit this for each release)
|
||||
//
|
||||
"0.12.1-alpha.1"
|
||||
//
|
||||
// Must follow the format described here:
|
||||
//
|
||||
// http://semver.org/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
;
|
||||
|
||||
return rawText;
|
||||
}
|
||||
|
||||
BuildInfo::Protocol const& BuildInfo::getCurrentProtocol ()
|
||||
{
|
||||
static Protocol currentProtocol (
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// The protocol version we speak and prefer (edit this if necessary)
|
||||
//
|
||||
1, // major
|
||||
2 // minor
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
);
|
||||
|
||||
return currentProtocol;
|
||||
}
|
||||
|
||||
BuildInfo::Protocol const& BuildInfo::getMinimumProtocol ()
|
||||
{
|
||||
static Protocol minimumProtocol (
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// The oldest protocol version we will accept. (edit this if necessary)
|
||||
//
|
||||
1, // major
|
||||
2 // minor
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
);
|
||||
|
||||
return minimumProtocol;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Don't touch anything below this line
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
String const& BuildInfo::getVersionString ()
|
||||
{
|
||||
struct SanityChecker
|
||||
{
|
||||
SanityChecker ()
|
||||
{
|
||||
SemanticVersion v;
|
||||
|
||||
char const* const rawText = getRawVersionString ();
|
||||
|
||||
if (! v.parse (rawText) || v.print () != rawText)
|
||||
FatalError ("Bad server version string", __FILE__, __LINE__);
|
||||
|
||||
versionString = rawText;
|
||||
}
|
||||
|
||||
String versionString;
|
||||
};
|
||||
|
||||
static SanityChecker value;
|
||||
|
||||
return value.versionString;
|
||||
}
|
||||
|
||||
char const* BuildInfo::getFullVersionString ()
|
||||
{
|
||||
struct PrettyPrinter
|
||||
{
|
||||
PrettyPrinter ()
|
||||
{
|
||||
String s;
|
||||
|
||||
s << "Ripple-" << getVersionString ();
|
||||
|
||||
fullVersionString = s.toStdString ();
|
||||
}
|
||||
|
||||
std::string fullVersionString;
|
||||
};
|
||||
|
||||
static PrettyPrinter value;
|
||||
|
||||
return value.fullVersionString.c_str ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
BuildInfo::Protocol::Protocol ()
|
||||
: vmajor (0)
|
||||
, vminor (0)
|
||||
{
|
||||
}
|
||||
|
||||
BuildInfo::Protocol::Protocol (unsigned short major_, unsigned short minor_)
|
||||
: vmajor (major_)
|
||||
, vminor (minor_)
|
||||
{
|
||||
}
|
||||
|
||||
BuildInfo::Protocol::Protocol (PackedFormat packedVersion)
|
||||
{
|
||||
vmajor = (packedVersion >> 16) & 0xffff;
|
||||
vminor = (packedVersion & 0xffff);
|
||||
}
|
||||
|
||||
BuildInfo::Protocol::PackedFormat BuildInfo::Protocol::toPacked () const noexcept
|
||||
{
|
||||
return ((vmajor << 16) & 0xffff0000) | (vminor & 0xffff);
|
||||
}
|
||||
|
||||
std::string BuildInfo::Protocol::toStdString () const noexcept
|
||||
{
|
||||
String s;
|
||||
|
||||
s << String (vmajor) << "." << String (vminor);
|
||||
|
||||
return s.toStdString ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class BuildInfoTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
BuildInfoTests () : UnitTest ("BuildInfo", "ripple", runStartup)
|
||||
{
|
||||
}
|
||||
|
||||
void testVersion ()
|
||||
{
|
||||
beginTestCase ("version");
|
||||
|
||||
SemanticVersion v;
|
||||
|
||||
expect (v.parse (BuildInfo::getRawVersionString ()));
|
||||
}
|
||||
|
||||
void checkProtcol (unsigned short vmajor, unsigned short vminor)
|
||||
{
|
||||
typedef BuildInfo::Protocol P;
|
||||
|
||||
expect (P (P (vmajor, vminor).toPacked ()) == P (vmajor, vminor));
|
||||
}
|
||||
|
||||
void testProtocol ()
|
||||
{
|
||||
typedef BuildInfo::Protocol P;
|
||||
|
||||
beginTestCase ("protocol");
|
||||
|
||||
expect (P (0, 0).toPacked () == 0);
|
||||
expect (P (0, 1).toPacked () == 1);
|
||||
expect (P (0, 65535).toPacked () == 65535);
|
||||
|
||||
checkProtcol (0, 0);
|
||||
checkProtcol (0, 1);
|
||||
checkProtcol (0, 255);
|
||||
checkProtcol (0, 65535);
|
||||
checkProtcol (1, 0);
|
||||
checkProtcol (1, 65535);
|
||||
checkProtcol (65535, 65535);
|
||||
}
|
||||
|
||||
void testValues ()
|
||||
{
|
||||
beginTestCase ("comparison");
|
||||
|
||||
typedef BuildInfo::Protocol P;
|
||||
|
||||
expect (P(1,2) == P(1,2));
|
||||
expect (P(3,4) >= P(3,4));
|
||||
expect (P(5,6) <= P(5,6));
|
||||
expect (P(7,8) > P(6,7));
|
||||
expect (P(7,8) < P(8,9));
|
||||
expect (P(65535,0) < P(65535,65535));
|
||||
expect (P(65535,65535) >= P(65535,65535));
|
||||
|
||||
expect (BuildInfo::getCurrentProtocol () >= BuildInfo::getMinimumProtocol ());
|
||||
}
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
testVersion ();
|
||||
testProtocol ();
|
||||
testValues ();
|
||||
}
|
||||
};
|
||||
|
||||
static BuildInfoTests buildInfoTests;
|
||||
73
src/ripple_data/protocol/BuildInfo.h
Normal file
73
src/ripple_data/protocol/BuildInfo.h
Normal file
@@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_BUILDINFO_H_INCLUDED
|
||||
#define RIPPLE_BUILDINFO_H_INCLUDED
|
||||
|
||||
/** Versioning information for this build. */
|
||||
struct BuildInfo
|
||||
{
|
||||
/** Server version.
|
||||
|
||||
Follows the Semantic Versioning Specification:
|
||||
|
||||
http://semver.org/
|
||||
*/
|
||||
static String const& getVersionString ();
|
||||
|
||||
/** Full server version string.
|
||||
|
||||
This includes the name of the server. It is used in the peer
|
||||
protocol hello message and also the headers of some HTTP replies.
|
||||
*/
|
||||
static char const* getFullVersionString ();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** The wire protocol version.
|
||||
|
||||
The version consists of two unsigned 16 bit integers representing
|
||||
major and minor version numbers. All values are permissible.
|
||||
*/
|
||||
struct Protocol
|
||||
{
|
||||
unsigned short vmajor;
|
||||
unsigned short vminor;
|
||||
|
||||
//----
|
||||
|
||||
/** The serialized format of the protocol version. */
|
||||
typedef uint32 PackedFormat;
|
||||
|
||||
Protocol ();
|
||||
Protocol (unsigned short vmajor, unsigned short vminor);
|
||||
explicit Protocol (PackedFormat packedVersion);
|
||||
|
||||
PackedFormat toPacked () const noexcept;
|
||||
|
||||
std::string toStdString () const noexcept;
|
||||
|
||||
bool operator== (Protocol const& other) const noexcept { return toPacked () == other.toPacked (); }
|
||||
bool operator!= (Protocol const& other) const noexcept { return toPacked () != other.toPacked (); }
|
||||
bool operator>= (Protocol const& other) const noexcept { return toPacked () >= other.toPacked (); }
|
||||
bool operator<= (Protocol const& other) const noexcept { return toPacked () <= other.toPacked (); }
|
||||
bool operator> (Protocol const& other) const noexcept { return toPacked () > other.toPacked (); }
|
||||
bool operator< (Protocol const& other) const noexcept { return toPacked () < other.toPacked (); }
|
||||
};
|
||||
|
||||
/** The protocol version we speak and prefer. */
|
||||
static Protocol const& getCurrentProtocol ();
|
||||
|
||||
/** The oldest protocol version we will accept. */
|
||||
static Protocol const& getMinimumProtocol ();
|
||||
|
||||
private:
|
||||
friend class BuildInfoTests;
|
||||
|
||||
static char const* getRawVersionString ();
|
||||
};
|
||||
|
||||
#endif
|
||||
362
src/ripple_data/protocol/ripple.proto
Normal file
362
src/ripple_data/protocol/ripple.proto
Normal file
@@ -0,0 +1,362 @@
|
||||
package protocol;
|
||||
|
||||
enum MessageType
|
||||
{
|
||||
// core
|
||||
mtHELLO = 1;
|
||||
mtERROR_MSG = 2;
|
||||
mtPING = 3;
|
||||
mtPROOFOFWORK = 4;
|
||||
mtCLUSTER = 5;
|
||||
|
||||
// network presence detection
|
||||
mtGET_CONTACTS = 10;
|
||||
mtCONTACT = 11;
|
||||
mtGET_PEERS = 12;
|
||||
mtPEERS = 13;
|
||||
|
||||
// operations for 'small' nodes
|
||||
mtSEARCH_TRANSACTION = 20;
|
||||
mtGET_ACCOUNT = 21;
|
||||
mtACCOUNT = 22;
|
||||
|
||||
// transaction and ledger processing
|
||||
mtTRANSACTION = 30;
|
||||
mtGET_LEDGER = 31;
|
||||
mtLEDGER_DATA = 32;
|
||||
mtPROPOSE_LEDGER = 33;
|
||||
mtSTATUS_CHANGE = 34;
|
||||
mtHAVE_SET = 35;
|
||||
|
||||
// data replication and synchronization
|
||||
mtGET_VALIDATIONS = 40;
|
||||
mtVALIDATION = 41;
|
||||
mtGET_OBJECTS = 42;
|
||||
}
|
||||
|
||||
|
||||
// token, iterations, target, challenge = issue demand for proof of work
|
||||
// token, response = give solution to proof of work
|
||||
// token, result = report result of pow
|
||||
|
||||
message TMProofWork
|
||||
{
|
||||
required string token = 1;
|
||||
optional uint32 iterations = 2;
|
||||
optional bytes target = 3;
|
||||
optional bytes challenge = 4;
|
||||
optional bytes response = 5;
|
||||
|
||||
enum PowResult
|
||||
{
|
||||
powrOK = 0;
|
||||
powrREUSED = 1;
|
||||
powrEXPIRED = 2; // You took too long solving
|
||||
powrTOOEASY = 3; // Difficulty went way up, sorry
|
||||
powrINVALID = 4;
|
||||
powrDISCONNECT = 5; // We are disconnecting
|
||||
}
|
||||
optional PowResult result = 6;
|
||||
}
|
||||
|
||||
// Sent on connect
|
||||
message TMHello
|
||||
{
|
||||
required uint32 protoVersion = 1;
|
||||
required uint32 protoVersionMin = 2;
|
||||
required bytes nodePublic = 3;
|
||||
required bytes nodeProof = 4;
|
||||
optional string fullVersion = 5;
|
||||
optional uint64 netTime = 6;
|
||||
optional uint32 ipv4Port = 7;
|
||||
optional uint32 ledgerIndex = 8;
|
||||
optional bytes ledgerClosed = 9; // our last closed ledger
|
||||
optional bytes ledgerPrevious = 10; // the ledger before the last closed ledger
|
||||
optional bool nodePrivate = 11; // Request to not forward IP.
|
||||
optional TMProofWork proofOfWork = 12; // request/provide proof of work
|
||||
optional bool testNet = 13; // Running as testnet.
|
||||
}
|
||||
|
||||
// The status of a node in our cluster
|
||||
message TMClusterNode
|
||||
{
|
||||
required string publicKey = 1;
|
||||
required uint32 reportTime = 2;
|
||||
required uint32 nodeLoad = 3;
|
||||
optional string nodeName = 4;
|
||||
optional string address = 5;
|
||||
}
|
||||
|
||||
// The status of all nodes in the cluster
|
||||
message TMCluster
|
||||
{
|
||||
repeated TMClusterNode clusterNodes = 1;
|
||||
}
|
||||
|
||||
|
||||
// A transaction can have only one input and one output.
|
||||
// If you want to send an amount that is greater than any single address of yours
|
||||
// you must first combine coins from one address to another.
|
||||
|
||||
enum TransactionStatus
|
||||
{
|
||||
tsNEW = 1; // origin node did/could not validate
|
||||
tsCURRENT = 2; // scheduled to go in this ledger
|
||||
tsCOMMITED = 3; // in a closed ledger
|
||||
tsREJECT_CONFLICT = 4;
|
||||
tsREJECT_INVALID = 5;
|
||||
tsREJECT_FUNDS = 6;
|
||||
tsHELD_SEQ = 7;
|
||||
tsHELD_LEDGER = 8; // held for future ledger
|
||||
}
|
||||
|
||||
message TMTransaction
|
||||
{
|
||||
required bytes rawTransaction = 1;
|
||||
required TransactionStatus status = 2;
|
||||
optional uint64 receiveTimestamp = 3;
|
||||
optional bool checkedSignature = 4; // no vouches for signature being correct
|
||||
}
|
||||
|
||||
|
||||
enum NodeStatus
|
||||
{
|
||||
nsCONNECTING = 1; // acquiring connections
|
||||
nsCONNECTED = 2; // convinced we are connected to the real network
|
||||
nsMONITORING = 3; // we know what the previous ledger is
|
||||
nsVALIDATING = 4; // we have the full ledger contents
|
||||
nsSHUTTING = 5; // node is shutting down
|
||||
}
|
||||
|
||||
enum NodeEvent
|
||||
{
|
||||
neCLOSING_LEDGER = 1; // closing a ledger because its close time has come
|
||||
neACCEPTED_LEDGER = 2; // accepting a closed ledger, we have finished computing it
|
||||
neSWITCHED_LEDGER = 3; // changing due to network consensus
|
||||
neLOST_SYNC = 4;
|
||||
}
|
||||
|
||||
message TMStatusChange
|
||||
{
|
||||
optional NodeStatus newStatus = 1;
|
||||
optional NodeEvent newEvent = 2;
|
||||
optional uint32 ledgerSeq = 3;
|
||||
optional bytes ledgerHash = 4;
|
||||
optional bytes ledgerHashPrevious = 5;
|
||||
optional uint64 networkTime = 6;
|
||||
optional uint32 firstSeq = 7;
|
||||
optional uint32 lastSeq = 8;
|
||||
}
|
||||
|
||||
|
||||
// Announce to the network our position on a closing ledger
|
||||
message TMProposeSet
|
||||
{
|
||||
required uint32 proposeSeq = 1;
|
||||
required bytes currentTxHash = 2; // the hash of the ledger we are proposing
|
||||
required bytes nodePubKey = 3;
|
||||
required uint32 closeTime = 4;
|
||||
required bytes signature = 5; // signature of above fields
|
||||
optional bytes previousledger = 6;
|
||||
optional bool checkedSignature = 7; // node vouches signature is correct
|
||||
repeated bytes addedTransactions = 10; // not required if number is large
|
||||
repeated bytes removedTransactions = 11; // not required if number is large
|
||||
}
|
||||
|
||||
enum TxSetStatus
|
||||
{
|
||||
tsHAVE = 1; // We have this set locally
|
||||
tsCAN_GET = 2; // We have a peer with this set
|
||||
tsNEED = 3; // We need this set and can't get it
|
||||
}
|
||||
|
||||
message TMHaveTransactionSet
|
||||
{
|
||||
required TxSetStatus status = 1;
|
||||
required bytes hash = 2;
|
||||
}
|
||||
|
||||
|
||||
// Used to sign a final closed ledger after reprocessing
|
||||
message TMValidation
|
||||
{
|
||||
required bytes validation = 1; // in SerializedValidation signed form
|
||||
optional bool checkedSignature = 2; // node vouches signature is correct
|
||||
}
|
||||
|
||||
|
||||
message TMGetValidations
|
||||
{
|
||||
required uint32 ledgerIndex = 1;
|
||||
repeated bytes hanko = 2;
|
||||
optional uint32 count = 3; // get random validations
|
||||
}
|
||||
|
||||
|
||||
|
||||
message TMContact
|
||||
{
|
||||
required bytes pubKey = 1;
|
||||
required uint32 softwareVersion = 2;
|
||||
required uint32 protoVersion = 3;
|
||||
required uint64 nodeFlags = 4;
|
||||
required uint64 timestamp = 5;
|
||||
repeated bytes nodeInfo = 6;
|
||||
required bytes signature = 7;
|
||||
}
|
||||
|
||||
// request node information
|
||||
message TMGetContacts
|
||||
{
|
||||
repeated bytes nodeIDs = 1; // specific nodes we want
|
||||
optional uint32 nodeCount = 2; // get some random nodes
|
||||
}
|
||||
|
||||
message TMGetPeers
|
||||
{
|
||||
required uint32 doWeNeedThis = 1; // yes since you are asserting that the packet size isn't 0 in PackedMessage
|
||||
}
|
||||
|
||||
message TMIPv4EndPoint
|
||||
{
|
||||
required uint32 ipv4 = 1;
|
||||
required uint32 ipv4Port = 2;
|
||||
}
|
||||
|
||||
message TMPeers
|
||||
{
|
||||
repeated TMIPv4EndPoint nodes = 1;
|
||||
}
|
||||
|
||||
|
||||
message TMSearchTransaction
|
||||
{
|
||||
required uint32 maxTrans = 1;
|
||||
optional bytes toAccount = 2;
|
||||
optional bytes fromAccount = 3;
|
||||
optional uint32 minLedger = 4;
|
||||
optional bytes fromAcctSeq = 5;
|
||||
repeated bytes transID = 6;
|
||||
}
|
||||
|
||||
message TMGetAccount
|
||||
{
|
||||
repeated bytes acctID = 1;
|
||||
optional uint32 seq = 2;
|
||||
}
|
||||
|
||||
message Account
|
||||
{
|
||||
required bytes accountID = 1;
|
||||
required uint64 balance = 2;
|
||||
required uint32 accountSeq = 3;
|
||||
required uint32 ledgerSeq = 4;
|
||||
}
|
||||
|
||||
message TMAccount
|
||||
{
|
||||
repeated Account accounts = 1;
|
||||
optional uint32 seq = 2;
|
||||
}
|
||||
|
||||
message TMIndexedObject
|
||||
{
|
||||
optional bytes hash = 1;
|
||||
optional bytes nodeID = 2;
|
||||
optional bytes index = 3;
|
||||
optional bytes data = 4;
|
||||
optional uint32 ledgerSeq = 5;
|
||||
}
|
||||
|
||||
message TMGetObjectByHash
|
||||
{
|
||||
enum ObjectType {
|
||||
otUNKNOWN = 0;
|
||||
otLEDGER = 1;
|
||||
otTRANSACTION = 2;
|
||||
otTRANSACTION_NODE = 3;
|
||||
otSTATE_NODE = 4;
|
||||
otCAS_OBJECT = 5;
|
||||
otFETCH_PACK = 6;
|
||||
}
|
||||
|
||||
required ObjectType type = 1;
|
||||
required bool query = 2; // is this a query or a reply?
|
||||
optional uint32 seq = 3; // used to match replies to queries
|
||||
optional bytes ledgerHash = 4; // the hash of the ledger these queries are for
|
||||
optional bool fat = 5; // return related nodes
|
||||
repeated TMIndexedObject objects = 6; // the specific objects requested
|
||||
}
|
||||
|
||||
|
||||
message TMLedgerNode
|
||||
{
|
||||
required bytes nodedata = 1;
|
||||
optional bytes nodeid = 2; // missing for ledger base data
|
||||
}
|
||||
|
||||
enum TMLedgerInfoType
|
||||
{
|
||||
liBASE = 0; // basic ledger info
|
||||
liTX_NODE = 1; // transaction node
|
||||
liAS_NODE = 2; // account state node
|
||||
liTS_CANDIDATE = 3; // candidate transaction set
|
||||
}
|
||||
|
||||
enum TMLedgerType
|
||||
{
|
||||
ltACCEPTED = 0;
|
||||
ltCURRENT = 1;
|
||||
ltCLOSED = 2;
|
||||
}
|
||||
|
||||
enum TMQueryType
|
||||
{
|
||||
qtINDIRECT = 0;
|
||||
}
|
||||
|
||||
message TMGetLedger
|
||||
{
|
||||
required TMLedgerInfoType itype = 1;
|
||||
optional TMLedgerType ltype = 2;
|
||||
optional bytes ledgerHash = 3; // Can also be the transaction set hash if liTS_CANDIDATE
|
||||
optional uint32 ledgerSeq = 4;
|
||||
repeated bytes nodeIDs = 5;
|
||||
optional uint64 requestCookie = 6;
|
||||
optional TMQueryType queryType = 7;
|
||||
}
|
||||
|
||||
enum TMReplyError
|
||||
{
|
||||
reNO_LEDGER = 1; // We don't have the ledger you are asking about
|
||||
reNO_NODE = 2; // We don't have any of the nodes you are asking for
|
||||
}
|
||||
|
||||
message TMLedgerData
|
||||
{
|
||||
required bytes ledgerHash = 1;
|
||||
required uint32 ledgerSeq = 2;
|
||||
required TMLedgerInfoType type = 3;
|
||||
repeated TMLedgerNode nodes = 4;
|
||||
optional uint32 requestCookie = 5;
|
||||
optional TMReplyError error = 6;
|
||||
}
|
||||
|
||||
message TMPing
|
||||
{
|
||||
enum pingType {
|
||||
ptPING = 0; // we want a reply
|
||||
ptPONG = 1; // this is a reply
|
||||
}
|
||||
required pingType type = 1;
|
||||
optional uint32 seq = 2; // detect stale replies, ensure other side is reading
|
||||
optional uint64 pingTime = 3; // know when we think we sent the ping
|
||||
optional uint64 netTime = 4;
|
||||
}
|
||||
|
||||
|
||||
message TMErrorMsg
|
||||
{
|
||||
optional int32 errorCode = 1;
|
||||
optional string message = 2;
|
||||
}
|
||||
144
src/ripple_data/protocol/ripple_FieldNames.cpp
Normal file
144
src/ripple_data/protocol/ripple_FieldNames.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// These must stay at the top of this file
|
||||
std::map<int, SField::ptr> SField::codeToField;
|
||||
int SField::num = 0;
|
||||
|
||||
|
||||
// Solve construction issues for objects with static storage duration.
|
||||
SField::StaticLockType& SField::getMutex ()
|
||||
{
|
||||
static StaticLockType mutex ("SField", __FILE__, __LINE__);
|
||||
return mutex;
|
||||
}
|
||||
|
||||
SField sfInvalid (-1), sfGeneric (0);
|
||||
SField sfLedgerEntry (STI_LEDGERENTRY, 1, "LedgerEntry");
|
||||
SField sfTransaction (STI_TRANSACTION, 1, "Transaction");
|
||||
SField sfValidation (STI_VALIDATION, 1, "Validation");
|
||||
SField sfHash (STI_HASH256, 257, "hash");
|
||||
SField sfIndex (STI_HASH256, 258, "index");
|
||||
|
||||
#define FIELD(name, type, index) SField sf##name(FIELD_CODE(STI_##type, index), STI_##type, index, #name);
|
||||
#define TYPE(name, type, index)
|
||||
#include "../protocol/ripple_SerializeDeclarations.h"
|
||||
#undef FIELD
|
||||
#undef TYPE
|
||||
|
||||
static int initFields ()
|
||||
{
|
||||
sfTxnSignature.notSigningField ();
|
||||
sfTxnSignatures.notSigningField ();
|
||||
sfSignature.notSigningField ();
|
||||
|
||||
sfIndexes.setMeta (SField::sMD_Never);
|
||||
sfPreviousTxnID.setMeta (SField::sMD_DeleteFinal);
|
||||
sfPreviousTxnLgrSeq.setMeta (SField::sMD_DeleteFinal);
|
||||
sfLedgerEntryType.setMeta (SField::sMD_Never);
|
||||
sfRootIndex.setMeta (SField::sMD_Always);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static const int f = initFields ();
|
||||
|
||||
|
||||
SField::SField (SerializedTypeID tid, int fv) : fieldCode (FIELD_CODE (tid, fv)), fieldType (tid), fieldValue (fv),
|
||||
fieldMeta (sMD_Default), fieldNum (++num), signingField (true)
|
||||
{
|
||||
// call with the map mutex
|
||||
fieldName = lexicalCast <std::string> (tid) + "/" + lexicalCast <std::string> (fv);
|
||||
codeToField[fieldCode] = this;
|
||||
assert ((fv != 1) || ((tid != STI_ARRAY) && (tid != STI_OBJECT)));
|
||||
}
|
||||
|
||||
SField::ref SField::getField (int code)
|
||||
{
|
||||
int type = code >> 16;
|
||||
int field = code % 0xffff;
|
||||
|
||||
if ((type <= 0) || (field <= 0))
|
||||
return sfInvalid;
|
||||
|
||||
StaticScopedLockType sl (getMutex (), __FILE__, __LINE__);
|
||||
|
||||
std::map<int, SField::ptr>::iterator it = codeToField.find (code);
|
||||
|
||||
if (it != codeToField.end ())
|
||||
return * (it->second);
|
||||
|
||||
if (field > 255) // don't dynamically extend types that have no binary encoding
|
||||
return sfInvalid;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// types we are willing to dynamically extend
|
||||
|
||||
#define FIELD(name, type, index)
|
||||
#define TYPE(name, type, index) case STI_##type:
|
||||
#include "../protocol/ripple_SerializeDeclarations.h"
|
||||
#undef FIELD
|
||||
#undef TYPE
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
return * (new SField (static_cast<SerializedTypeID> (type), field));
|
||||
}
|
||||
|
||||
int SField::compare (SField::ref f1, SField::ref f2)
|
||||
{
|
||||
// -1 = f1 comes before f2, 0 = illegal combination, 1 = f1 comes after f2
|
||||
if ((f1.fieldCode <= 0) || (f2.fieldCode <= 0))
|
||||
return 0;
|
||||
|
||||
if (f1.fieldCode < f2.fieldCode)
|
||||
return -1;
|
||||
|
||||
if (f2.fieldCode < f1.fieldCode)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string SField::getName () const
|
||||
{
|
||||
if (!fieldName.empty ())
|
||||
return fieldName;
|
||||
|
||||
if (fieldValue == 0)
|
||||
return "";
|
||||
|
||||
return lexicalCastThrow <std::string> (static_cast<int> (fieldType)) + "/" +
|
||||
lexicalCastThrow <std::string> (fieldValue);
|
||||
}
|
||||
|
||||
SField::ref SField::getField (const std::string& fieldName)
|
||||
{
|
||||
// OPTIMIZEME me with a map. CHECKME this is case sensitive
|
||||
StaticScopedLockType sl (getMutex (), __FILE__, __LINE__);
|
||||
typedef std::map<int, SField::ptr>::value_type int_sfref_pair;
|
||||
BOOST_FOREACH (const int_sfref_pair & fieldPair, codeToField)
|
||||
{
|
||||
if (fieldPair.second->fieldName == fieldName)
|
||||
return * (fieldPair.second);
|
||||
}
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
SField::~SField ()
|
||||
{
|
||||
StaticScopedLockType sl (getMutex (), __FILE__, __LINE__);
|
||||
std::map<int, ptr>::iterator it = codeToField.find (fieldCode);
|
||||
|
||||
if ((it != codeToField.end ()) && (it->second == this))
|
||||
codeToField.erase (it);
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
219
src/ripple_data/protocol/ripple_FieldNames.h
Normal file
219
src/ripple_data/protocol/ripple_FieldNames.h
Normal file
@@ -0,0 +1,219 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_FIELDNAMES_H
|
||||
#define RIPPLE_FIELDNAMES_H
|
||||
|
||||
// VFALCO TODO lose the macro.
|
||||
#define FIELD_CODE(type, index) ((static_cast<int>(type) << 16) | index)
|
||||
|
||||
enum SerializedTypeID
|
||||
{
|
||||
// special types
|
||||
STI_UNKNOWN = -2,
|
||||
STI_DONE = -1,
|
||||
STI_NOTPRESENT = 0,
|
||||
|
||||
#define TYPE(name, field, value) STI_##field = value,
|
||||
#define FIELD(name, field, value)
|
||||
#include "../protocol/ripple_SerializeDeclarations.h"
|
||||
#undef TYPE
|
||||
#undef FIELD
|
||||
|
||||
// high level types
|
||||
STI_TRANSACTION = 10001,
|
||||
STI_LEDGERENTRY = 10002,
|
||||
STI_VALIDATION = 10003,
|
||||
};
|
||||
|
||||
/** Identifies fields.
|
||||
|
||||
Fields are necessary to tag data in signed transactions so that
|
||||
the binary format of the transaction can be canonicalized.
|
||||
*/
|
||||
// VFALCO TODO rename this to NamedField
|
||||
class SField
|
||||
{
|
||||
public:
|
||||
typedef const SField& ref;
|
||||
typedef SField const* ptr;
|
||||
|
||||
static const int sMD_Never = 0x00;
|
||||
static const int sMD_ChangeOrig = 0x01; // original value when it changes
|
||||
static const int sMD_ChangeNew = 0x02; // new value when it changes
|
||||
static const int sMD_DeleteFinal = 0x04; // final value when it is deleted
|
||||
static const int sMD_Create = 0x08; // value when it's created
|
||||
static const int sMD_Always = 0x10; // value when node containing it is affected at all
|
||||
static const int sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create;
|
||||
|
||||
public:
|
||||
|
||||
const int fieldCode; // (type<<16)|index
|
||||
const SerializedTypeID fieldType; // STI_*
|
||||
const int fieldValue; // Code number for protocol
|
||||
std::string fieldName;
|
||||
int fieldMeta;
|
||||
int fieldNum;
|
||||
bool signingField;
|
||||
|
||||
SField (int fc, SerializedTypeID tid, int fv, const char* fn)
|
||||
: fieldCode (fc)
|
||||
, fieldType (tid)
|
||||
, fieldValue (fv)
|
||||
, fieldName (fn)
|
||||
, fieldMeta (sMD_Default)
|
||||
, signingField (true)
|
||||
{
|
||||
StaticScopedLockType sl (getMutex (), __FILE__, __LINE__);
|
||||
|
||||
codeToField[fieldCode] = this;
|
||||
|
||||
fieldNum = ++num;
|
||||
}
|
||||
|
||||
SField (SerializedTypeID tid, int fv, const char* fn)
|
||||
: fieldCode (FIELD_CODE (tid, fv))
|
||||
, fieldType (tid)
|
||||
, fieldValue (fv)
|
||||
, fieldName (fn)
|
||||
, fieldMeta (sMD_Default)
|
||||
, signingField (true)
|
||||
{
|
||||
StaticScopedLockType sl (getMutex (), __FILE__, __LINE__);
|
||||
|
||||
codeToField[fieldCode] = this;
|
||||
|
||||
fieldNum = ++num;
|
||||
}
|
||||
|
||||
explicit SField (int fc)
|
||||
: fieldCode (fc)
|
||||
, fieldType (STI_UNKNOWN)
|
||||
, fieldValue (0)
|
||||
, fieldMeta (sMD_Never)
|
||||
, signingField (true)
|
||||
{
|
||||
StaticScopedLockType sl (getMutex (), __FILE__, __LINE__);
|
||||
fieldNum = ++num;
|
||||
}
|
||||
|
||||
~SField ();
|
||||
|
||||
static SField::ref getField (int fieldCode);
|
||||
static SField::ref getField (const std::string& fieldName);
|
||||
static SField::ref getField (int type, int value)
|
||||
{
|
||||
return getField (FIELD_CODE (type, value));
|
||||
}
|
||||
static SField::ref getField (SerializedTypeID type, int value)
|
||||
{
|
||||
return getField (FIELD_CODE (type, value));
|
||||
}
|
||||
|
||||
std::string getName () const;
|
||||
bool hasName () const
|
||||
{
|
||||
return !fieldName.empty ();
|
||||
}
|
||||
|
||||
bool isGeneric () const
|
||||
{
|
||||
return fieldCode == 0;
|
||||
}
|
||||
bool isInvalid () const
|
||||
{
|
||||
return fieldCode == -1;
|
||||
}
|
||||
bool isUseful () const
|
||||
{
|
||||
return fieldCode > 0;
|
||||
}
|
||||
bool isKnown () const
|
||||
{
|
||||
return fieldType != STI_UNKNOWN;
|
||||
}
|
||||
bool isBinary () const
|
||||
{
|
||||
return fieldValue < 256;
|
||||
}
|
||||
|
||||
// VFALCO NOTE What is a discardable field?
|
||||
bool isDiscardable () const
|
||||
{
|
||||
return fieldValue > 256;
|
||||
}
|
||||
|
||||
int getCode () const
|
||||
{
|
||||
return fieldCode;
|
||||
}
|
||||
int getNum () const
|
||||
{
|
||||
return fieldNum;
|
||||
}
|
||||
static int getNumFields ()
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
bool isSigningField () const
|
||||
{
|
||||
return signingField;
|
||||
}
|
||||
void notSigningField ()
|
||||
{
|
||||
signingField = false;
|
||||
}
|
||||
bool shouldMeta (int c) const
|
||||
{
|
||||
return (fieldMeta & c) != 0;
|
||||
}
|
||||
void setMeta (int c)
|
||||
{
|
||||
fieldMeta = c;
|
||||
}
|
||||
|
||||
bool shouldInclude (bool withSigningField) const
|
||||
{
|
||||
return (fieldValue < 256) && (withSigningField || signingField);
|
||||
}
|
||||
|
||||
bool operator== (const SField& f) const
|
||||
{
|
||||
return fieldCode == f.fieldCode;
|
||||
}
|
||||
|
||||
bool operator!= (const SField& f) const
|
||||
{
|
||||
return fieldCode != f.fieldCode;
|
||||
}
|
||||
|
||||
static int compare (SField::ref f1, SField::ref f2);
|
||||
|
||||
// VFALCO TODO make these private
|
||||
protected:
|
||||
static std::map<int, ptr> codeToField;
|
||||
|
||||
typedef RippleMutex StaticLockType;
|
||||
typedef StaticLockType::ScopedLockType StaticScopedLockType;
|
||||
|
||||
static StaticLockType& getMutex ();
|
||||
|
||||
// VFALCO NOTE can this be replaced with an atomic int???!
|
||||
static int num;
|
||||
|
||||
SField (SerializedTypeID id, int val);
|
||||
};
|
||||
|
||||
extern SField sfInvalid, sfGeneric, sfLedgerEntry, sfTransaction, sfValidation;
|
||||
|
||||
#define FIELD(name, type, index) extern SField sf##name;
|
||||
#define TYPE(name, type, index)
|
||||
#include "../protocol/ripple_SerializeDeclarations.h"
|
||||
#undef FIELD
|
||||
#undef TYPE
|
||||
|
||||
#endif
|
||||
69
src/ripple_data/protocol/ripple_HashPrefix.h
Normal file
69
src/ripple_data/protocol/ripple_HashPrefix.h
Normal file
@@ -0,0 +1,69 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_HASHPREFIX_H
|
||||
#define RIPPLE_HASHPREFIX_H
|
||||
|
||||
/** Prefix for hashing functions.
|
||||
|
||||
These prefixes are inserted before the source material used to
|
||||
generate various hashes. This is done to put each hash in its own
|
||||
"space." This way, two different types of objects with the
|
||||
same binary data will produce different hashes.
|
||||
|
||||
Each prefix is a 4-byte value with the last byte set to zero
|
||||
and the first three bytes formed from the ASCII equivalent of
|
||||
some arbitrary string. For example "TXN".
|
||||
|
||||
@note Hash prefixes are part of the Ripple protocol.
|
||||
|
||||
@ingroup protocol
|
||||
*/
|
||||
// VFALCO NOTE there are ledger entry prefixes too but they are only
|
||||
// 1 byte, find out why they are different. Maybe we should
|
||||
// group them all together?
|
||||
//
|
||||
struct HashPrefix
|
||||
{
|
||||
// VFALCO TODO Make these Doxygen comments and expand the
|
||||
// description to complete, concise sentences.
|
||||
//
|
||||
|
||||
// transaction plus signature to give transaction ID
|
||||
static uint32 const transactionID = 0x54584E00; // 'TXN'
|
||||
|
||||
// transaction plus metadata
|
||||
static uint32 const txNode = 0x534E4400; // 'TND'
|
||||
|
||||
// account state
|
||||
static uint32 const leafNode = 0x4D4C4E00; // 'MLN'
|
||||
|
||||
// inner node in tree
|
||||
static uint32 const innerNode = 0x4D494E00; // 'MIN'
|
||||
|
||||
// ledger master data for signing
|
||||
static uint32 const ledgerMaster = 0x4C575200; // 'LGR'
|
||||
|
||||
// inner transaction to sign
|
||||
static uint32 const txSign = 0x53545800; // 'STX'
|
||||
|
||||
// validation for signing
|
||||
static uint32 const validation = 0x56414C00; // 'VAL'
|
||||
|
||||
// proposal for signing
|
||||
static uint32 const proposal = 0x50525000; // 'PRP'
|
||||
|
||||
// inner transaction to sign (TESTNET)
|
||||
static uint32 const txSignTestnet = 0x73747800; // 'stx'
|
||||
|
||||
// validation for signing (TESTNET)
|
||||
static uint32 const validationTestnet = 0x76616C00; // 'val'
|
||||
|
||||
// proposal for signing (TESTNET)
|
||||
static uint32 const proposalTestnet = 0x70727000; // 'prp'
|
||||
};
|
||||
|
||||
#endif
|
||||
172
src/ripple_data/protocol/ripple_KnownFormats.h
Normal file
172
src/ripple_data/protocol/ripple_KnownFormats.h
Normal file
@@ -0,0 +1,172 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_KNOWNFORMATS_H_INCLUDED
|
||||
#define RIPPLE_KNOWNFORMATS_H_INCLUDED
|
||||
|
||||
/** Manages a list of known formats.
|
||||
|
||||
Each format has a name, an associated KeyType (typically an enumeration),
|
||||
and a predefined @ref SOElement.
|
||||
|
||||
@tparam KeyType The type of key identifying the format.
|
||||
*/
|
||||
template <class KeyType>
|
||||
class KnownFormats
|
||||
{
|
||||
public:
|
||||
/** A known format.
|
||||
*/
|
||||
class Item
|
||||
{
|
||||
public:
|
||||
Item (char const* name, KeyType type)
|
||||
: m_name (name)
|
||||
, m_type (type)
|
||||
{
|
||||
}
|
||||
|
||||
Item& operator<< (SOElement const& el)
|
||||
{
|
||||
elements.push_back (el);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Retrieve the name of the format.
|
||||
*/
|
||||
std::string const& getName () const noexcept
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/** Retrieve the transaction type this format represents.
|
||||
*/
|
||||
KeyType getType () const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
public:
|
||||
// VFALCO TODO make an accessor for this
|
||||
SOTemplate elements;
|
||||
|
||||
private:
|
||||
std::string const m_name;
|
||||
KeyType const m_type;
|
||||
};
|
||||
|
||||
private:
|
||||
// VFALCO TODO use String instead of std::string
|
||||
typedef std::map <std::string, Item*> NameMap;
|
||||
typedef std::map <KeyType, Item*> TypeMap;
|
||||
|
||||
public:
|
||||
/** Create the known formats object.
|
||||
|
||||
Derived classes will load the object will all the known formats.
|
||||
*/
|
||||
KnownFormats ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Destroy the known formats object.
|
||||
|
||||
The defined formats are deleted.
|
||||
*/
|
||||
~KnownFormats ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Retrieve the type for a format specified by name.
|
||||
|
||||
If the format name is unknown, an exception is thrown.
|
||||
|
||||
@param name The name of the type.
|
||||
@return The type.
|
||||
*/
|
||||
KeyType findTypeByName (std::string const name) const
|
||||
{
|
||||
Item const* const result = findByName (name);
|
||||
|
||||
if (result != nullptr)
|
||||
{
|
||||
return result->getType ();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error ("Unknown format name");
|
||||
}
|
||||
}
|
||||
|
||||
/** Retrieve a format based on its type.
|
||||
*/
|
||||
// VFALCO TODO Can we just return the SOElement& ?
|
||||
Item const* findByType (KeyType type) const noexcept
|
||||
{
|
||||
Item* result = nullptr;
|
||||
|
||||
typename TypeMap::const_iterator const iter = m_types.find (type);
|
||||
|
||||
if (iter != m_types.end ())
|
||||
{
|
||||
result = iter->second;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Retrieve a format based on its name.
|
||||
*/
|
||||
Item const* findByName (std::string const& name) const noexcept
|
||||
{
|
||||
Item* result = nullptr;
|
||||
|
||||
typename NameMap::const_iterator const iter = m_names.find (name);
|
||||
|
||||
if (iter != m_names.end ())
|
||||
{
|
||||
result = iter->second;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Add a new format.
|
||||
|
||||
The new format has the set of common fields already added.
|
||||
|
||||
@param name The name of this format.
|
||||
@param type The type of this format.
|
||||
|
||||
@return The created format.
|
||||
*/
|
||||
Item& add (char const* name, KeyType type)
|
||||
{
|
||||
Item& item = *m_formats.add (new Item (name, type));
|
||||
|
||||
addCommonFields (item);
|
||||
|
||||
m_types [item.getType ()] = &item;
|
||||
m_names [item.getName ()] = &item;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/** Adds common fields.
|
||||
|
||||
This is called for every new item.
|
||||
*/
|
||||
virtual void addCommonFields (Item& item) = 0;
|
||||
|
||||
private:
|
||||
OwnedArray <Item> m_formats;
|
||||
NameMap m_names;
|
||||
TypeMap m_types;
|
||||
};
|
||||
|
||||
#endif
|
||||
120
src/ripple_data/protocol/ripple_LedgerFormats.cpp
Normal file
120
src/ripple_data/protocol/ripple_LedgerFormats.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
LedgerFormats::LedgerFormats ()
|
||||
: SharedSingleton <LedgerFormats> (SingletonLifetime::persistAfterCreation)
|
||||
{
|
||||
add ("AccountRoot", ltACCOUNT_ROOT)
|
||||
<< SOElement (sfAccount, SOE_REQUIRED)
|
||||
<< SOElement (sfSequence, SOE_REQUIRED)
|
||||
<< SOElement (sfBalance, SOE_REQUIRED)
|
||||
<< SOElement (sfOwnerCount, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement (sfRegularKey, SOE_OPTIONAL)
|
||||
<< SOElement (sfEmailHash, SOE_OPTIONAL)
|
||||
<< SOElement (sfWalletLocator, SOE_OPTIONAL)
|
||||
<< SOElement (sfWalletSize, SOE_OPTIONAL)
|
||||
<< SOElement (sfMessageKey, SOE_OPTIONAL)
|
||||
<< SOElement (sfTransferRate, SOE_OPTIONAL)
|
||||
<< SOElement (sfDomain, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("Contract", ltCONTRACT)
|
||||
<< SOElement (sfAccount, SOE_REQUIRED)
|
||||
<< SOElement (sfBalance, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement (sfIssuer, SOE_REQUIRED)
|
||||
<< SOElement (sfOwner, SOE_REQUIRED)
|
||||
<< SOElement (sfExpiration, SOE_REQUIRED)
|
||||
<< SOElement (sfBondAmount, SOE_REQUIRED)
|
||||
<< SOElement (sfCreateCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfFundCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfRemoveCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfExpireCode, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("DirectoryNode", ltDIR_NODE)
|
||||
<< SOElement (sfOwner, SOE_OPTIONAL) // for owner directories
|
||||
<< SOElement (sfTakerPaysCurrency, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfTakerPaysIssuer, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfTakerGetsCurrency, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfTakerGetsIssuer, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfExchangeRate, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfIndexes, SOE_REQUIRED)
|
||||
<< SOElement (sfRootIndex, SOE_REQUIRED)
|
||||
<< SOElement (sfIndexNext, SOE_OPTIONAL)
|
||||
<< SOElement (sfIndexPrevious, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("GeneratorMap", ltGENERATOR_MAP)
|
||||
<< SOElement (sfGenerator, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
add ("Nickname", ltNICKNAME)
|
||||
<< SOElement (sfAccount, SOE_REQUIRED)
|
||||
<< SOElement (sfMinimumOffer, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("Offer", ltOFFER)
|
||||
<< SOElement (sfAccount, SOE_REQUIRED)
|
||||
<< SOElement (sfSequence, SOE_REQUIRED)
|
||||
<< SOElement (sfTakerPays, SOE_REQUIRED)
|
||||
<< SOElement (sfTakerGets, SOE_REQUIRED)
|
||||
<< SOElement (sfBookDirectory, SOE_REQUIRED)
|
||||
<< SOElement (sfBookNode, SOE_REQUIRED)
|
||||
<< SOElement (sfOwnerNode, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement (sfExpiration, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("RippleState", ltRIPPLE_STATE)
|
||||
<< SOElement (sfBalance, SOE_REQUIRED)
|
||||
<< SOElement (sfLowLimit, SOE_REQUIRED)
|
||||
<< SOElement (sfHighLimit, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement (sfLowNode, SOE_OPTIONAL)
|
||||
<< SOElement (sfLowQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement (sfLowQualityOut, SOE_OPTIONAL)
|
||||
<< SOElement (sfHighNode, SOE_OPTIONAL)
|
||||
<< SOElement (sfHighQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement (sfHighQualityOut, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("LedgerHashes", ltLEDGER_HASHES)
|
||||
<< SOElement (sfFirstLedgerSequence, SOE_OPTIONAL) // Remove if we do a ledger restart
|
||||
<< SOElement (sfLastLedgerSequence, SOE_OPTIONAL)
|
||||
<< SOElement (sfHashes, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
add ("EnabledFeatures", ltFEATURES)
|
||||
<< SOElement (sfFeatures, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
add ("FeeSettings", ltFEE_SETTINGS)
|
||||
<< SOElement (sfBaseFee, SOE_REQUIRED)
|
||||
<< SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
|
||||
<< SOElement (sfReserveBase, SOE_REQUIRED)
|
||||
<< SOElement (sfReserveIncrement, SOE_REQUIRED)
|
||||
;
|
||||
}
|
||||
|
||||
LedgerFormats* LedgerFormats::createInstance ()
|
||||
{
|
||||
return new LedgerFormats;
|
||||
}
|
||||
|
||||
void LedgerFormats::addCommonFields (Item& item)
|
||||
{
|
||||
item
|
||||
<< SOElement(sfLedgerIndex, SOE_OPTIONAL)
|
||||
<< SOElement(sfLedgerEntryType, SOE_REQUIRED)
|
||||
<< SOElement(sfFlags, SOE_REQUIRED)
|
||||
;
|
||||
}
|
||||
121
src/ripple_data/protocol/ripple_LedgerFormats.h
Normal file
121
src/ripple_data/protocol/ripple_LedgerFormats.h
Normal file
@@ -0,0 +1,121 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGERFORMATS_H_INCLUDED
|
||||
#define RIPPLE_LEDGERFORMATS_H_INCLUDED
|
||||
|
||||
/** Ledger entry types.
|
||||
|
||||
These are stored in serialized data.
|
||||
|
||||
@note Changing these values results in a hard fork.
|
||||
|
||||
@ingroup protocol
|
||||
*/
|
||||
// Used as the type of a transaction or the type of a ledger entry.
|
||||
enum LedgerEntryType
|
||||
{
|
||||
ltINVALID = -1,
|
||||
|
||||
ltACCOUNT_ROOT = 'a',
|
||||
|
||||
/** Directory node.
|
||||
|
||||
A directory is a vector 256-bit values. Usually they represent
|
||||
hashes of other objects in the ledger.
|
||||
|
||||
Used in an append-only fashion.
|
||||
|
||||
(There's a little more information than this, see the template)
|
||||
*/
|
||||
ltDIR_NODE = 'd',
|
||||
|
||||
ltGENERATOR_MAP = 'g',
|
||||
|
||||
/** Describes a trust line.
|
||||
*/
|
||||
// VFALCO TODO Rename to TrustLine or something similar.
|
||||
ltRIPPLE_STATE = 'r',
|
||||
|
||||
/** Deprecated.
|
||||
*/
|
||||
ltNICKNAME = 'n',
|
||||
|
||||
ltOFFER = 'o',
|
||||
|
||||
ltCONTRACT = 'c',
|
||||
|
||||
ltLEDGER_HASHES = 'h',
|
||||
|
||||
ltFEATURES = 'f',
|
||||
|
||||
ltFEE_SETTINGS = 's',
|
||||
};
|
||||
|
||||
/**
|
||||
@ingroup protocol
|
||||
*/
|
||||
// Used as a prefix for computing ledger indexes (keys).
|
||||
// VFALCO TODO Why are there a separate set of prefixes? i.e. class HashPrefix
|
||||
enum LedgerNameSpace
|
||||
{
|
||||
spaceAccount = 'a',
|
||||
spaceDirNode = 'd',
|
||||
spaceGenerator = 'g',
|
||||
spaceNickname = 'n',
|
||||
spaceRipple = 'r',
|
||||
spaceOffer = 'o', // Entry for an offer.
|
||||
spaceOwnerDir = 'O', // Directory of things owned by an account.
|
||||
spaceBookDir = 'B', // Directory of order books.
|
||||
spaceContract = 'c',
|
||||
spaceSkipList = 's',
|
||||
spaceFeature = 'f',
|
||||
spaceFee = 'e',
|
||||
};
|
||||
|
||||
/**
|
||||
@ingroup protocol
|
||||
*/
|
||||
enum LedgerSpecificFlags
|
||||
{
|
||||
// ltACCOUNT_ROOT
|
||||
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
|
||||
lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments.
|
||||
lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs.
|
||||
lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP.
|
||||
lsfDisableMaster = 0x00100000, // True, force regular key
|
||||
|
||||
// ltOFFER
|
||||
lsfPassive = 0x00010000,
|
||||
lsfSell = 0x00020000, // True, offer was placed as a sell.
|
||||
|
||||
// ltRIPPLE_STATE
|
||||
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
|
||||
lsfHighReserve = 0x00020000,
|
||||
lsfLowAuth = 0x00040000,
|
||||
lsfHighAuth = 0x00080000,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Holds the list of known ledger entry formats.
|
||||
*/
|
||||
class LedgerFormats
|
||||
: public KnownFormats <LedgerEntryType>
|
||||
, public SharedSingleton <LedgerFormats>
|
||||
{
|
||||
private:
|
||||
LedgerFormats ();
|
||||
|
||||
public:
|
||||
static LedgerFormats* createInstance ();
|
||||
|
||||
private:
|
||||
void addCommonFields (Item& item);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
74
src/ripple_data/protocol/ripple_PackedMessage.cpp
Normal file
74
src/ripple_data/protocol/ripple_PackedMessage.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
PackedMessage::PackedMessage (::google::protobuf::Message const& message, int type)
|
||||
{
|
||||
unsigned const messageBytes = message.ByteSize ();
|
||||
|
||||
assert (messageBytes != 0);
|
||||
|
||||
mBuffer.resize (kHeaderBytes + messageBytes);
|
||||
|
||||
encodeHeader (messageBytes, type);
|
||||
|
||||
if (messageBytes != 0)
|
||||
{
|
||||
message.SerializeToArray (&mBuffer [PackedMessage::kHeaderBytes], messageBytes);
|
||||
|
||||
#ifdef BEAST_DEBUG
|
||||
//Log::out() << "PackedMessage: type=" << type << ", datalen=" << msg_size;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool PackedMessage::operator== (PackedMessage const& other) const
|
||||
{
|
||||
return mBuffer == other.mBuffer;
|
||||
}
|
||||
|
||||
unsigned PackedMessage::getLength (std::vector <uint8_t> const& buf)
|
||||
{
|
||||
unsigned result;
|
||||
|
||||
if (buf.size () >= PackedMessage::kHeaderBytes)
|
||||
{
|
||||
result = buf [0];
|
||||
result <<= 8;
|
||||
result |= buf [1];
|
||||
result <<= 8;
|
||||
result |= buf [2];
|
||||
result <<= 8;
|
||||
result |= buf [3];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int PackedMessage::getType (std::vector<uint8_t> const& buf)
|
||||
{
|
||||
if (buf.size () < PackedMessage::kHeaderBytes)
|
||||
return 0;
|
||||
|
||||
int ret = buf[4];
|
||||
ret <<= 8;
|
||||
ret |= buf[5];
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PackedMessage::encodeHeader (unsigned size, int type)
|
||||
{
|
||||
assert (mBuffer.size () >= PackedMessage::kHeaderBytes);
|
||||
mBuffer[0] = static_cast<boost::uint8_t> ((size >> 24) & 0xFF);
|
||||
mBuffer[1] = static_cast<boost::uint8_t> ((size >> 16) & 0xFF);
|
||||
mBuffer[2] = static_cast<boost::uint8_t> ((size >> 8) & 0xFF);
|
||||
mBuffer[3] = static_cast<boost::uint8_t> (size & 0xFF);
|
||||
mBuffer[4] = static_cast<boost::uint8_t> ((type >> 8) & 0xFF);
|
||||
mBuffer[5] = static_cast<boost::uint8_t> (type & 0xFF);
|
||||
}
|
||||
60
src/ripple_data/protocol/ripple_PackedMessage.h
Normal file
60
src/ripple_data/protocol/ripple_PackedMessage.h
Normal file
@@ -0,0 +1,60 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
//
|
||||
// packaging of messages into length/type-prepended buffers
|
||||
// ready for transmission.
|
||||
|
||||
#ifndef RIPPLE_PACKEDMESSAGE_H
|
||||
#define RIPPLE_PACKEDMESSAGE_H
|
||||
|
||||
// PackedMessage implements simple "packing" of protocol buffers Messages into
|
||||
// a string prepended by a header specifying the message length.
|
||||
// MessageType should be a Message class generated by the protobuf compiler.
|
||||
//
|
||||
|
||||
class PackedMessage : public boost::enable_shared_from_this <PackedMessage>
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr< ::google::protobuf::Message > MessagePointer;
|
||||
typedef boost::shared_ptr<PackedMessage> pointer;
|
||||
|
||||
public:
|
||||
/** Number of bytes in a message header.
|
||||
*/
|
||||
static unsigned const kHeaderBytes = 6;
|
||||
|
||||
PackedMessage (::google::protobuf::Message const& message, int type);
|
||||
|
||||
/** Retrieve the packed message data.
|
||||
*/
|
||||
// VFALCO TODO shouldn't this be const?
|
||||
std::vector <uint8_t>& getBuffer ()
|
||||
{
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
/** Determine bytewise equality.
|
||||
*/
|
||||
bool operator == (PackedMessage const& other) const;
|
||||
|
||||
/** Calculate the length of a packed message.
|
||||
*/
|
||||
static unsigned getLength (std::vector <uint8_t> const& buf);
|
||||
|
||||
/** Determine the type of a packed message.
|
||||
*/
|
||||
static int getType (std::vector <uint8_t> const& buf);
|
||||
|
||||
private:
|
||||
// Encodes the size and type into a header at the beginning of buf
|
||||
//
|
||||
void encodeHeader (unsigned size, int type);
|
||||
|
||||
std::vector <uint8_t> mBuffer;
|
||||
};
|
||||
|
||||
#endif /* PACKEDMESSAGE_H */
|
||||
|
||||
72
src/ripple_data/protocol/ripple_Protocol.h
Normal file
72
src/ripple_data/protocol/ripple_Protocol.h
Normal file
@@ -0,0 +1,72 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PROTOCOL_H
|
||||
#define RIPPLE_PROTOCOL_H
|
||||
|
||||
/** Protocol specific constants, types, and data.
|
||||
|
||||
This information is part of the Ripple protocol. Specifically,
|
||||
it is required for peers to be able to communicate with each other.
|
||||
|
||||
@note Changing these will create a hard fork.
|
||||
|
||||
@ingroup protocol
|
||||
@defgroup protocol
|
||||
*/
|
||||
struct Protocol
|
||||
{
|
||||
/** Smallest legal byte size of a transaction.
|
||||
*/
|
||||
static int const txMinSizeBytes = 32;
|
||||
|
||||
/** Largest legal byte size of a transaction.
|
||||
*/
|
||||
static int const txMaxSizeBytes = 1024 * 1024; // 1048576
|
||||
};
|
||||
|
||||
/*
|
||||
Hashes are used to uniquely identify objects like
|
||||
transactions, peers, validators, and accounts.
|
||||
|
||||
For historical reasons, some hashes are 256 bits and some are 160.
|
||||
|
||||
David:
|
||||
"The theory is that you may need to communicate public keys
|
||||
to others, so having them be shorter is a good idea. plus,
|
||||
you can't arbitrarily tweak them because you wouldn't know
|
||||
the corresponding private key anyway. So the security
|
||||
requirements aren't as great."
|
||||
*/
|
||||
|
||||
/** A ledger hash.
|
||||
*/
|
||||
typedef uint256 LedgerHash;
|
||||
|
||||
/** A ledger index.
|
||||
*/
|
||||
// VFALCO TODO pick one. I like Index since its not an abbreviation
|
||||
typedef uint32 LedgerIndex;
|
||||
// VFALCO NOTE "LedgerSeq" appears in some SQL statement text
|
||||
typedef uint32 LedgerSeq;
|
||||
|
||||
/** A transaction identifier.
|
||||
*/
|
||||
// VFALCO TODO maybe rename to TxHash
|
||||
typedef uint256 TxID;
|
||||
|
||||
/** A transaction index.
|
||||
*/
|
||||
typedef uint32 TxSeq; // VFALCO NOTE Should read TxIndex or TxNum
|
||||
|
||||
/** An account hash.
|
||||
|
||||
The hash is used to uniquely identify the account.
|
||||
*/
|
||||
//typedef uint160 AccountHash;
|
||||
//typedef uint260 ValidatorID;
|
||||
|
||||
#endif
|
||||
946
src/ripple_data/protocol/ripple_RippleAddress.cpp
Normal file
946
src/ripple_data/protocol/ripple_RippleAddress.cpp
Normal file
@@ -0,0 +1,946 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
SETUP_LOG (RippleAddress)
|
||||
|
||||
RippleAddress::RippleAddress ()
|
||||
: mIsValid (false)
|
||||
{
|
||||
nVersion = VER_NONE;
|
||||
}
|
||||
|
||||
void RippleAddress::clear ()
|
||||
{
|
||||
nVersion = VER_NONE;
|
||||
vchData.clear ();
|
||||
}
|
||||
|
||||
bool RippleAddress::isSet () const
|
||||
{
|
||||
return nVersion != VER_NONE;
|
||||
}
|
||||
|
||||
std::string RippleAddress::humanAddressType () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
return "VER_NONE";
|
||||
|
||||
case VER_NODE_PUBLIC:
|
||||
return "VER_NODE_PUBLIC";
|
||||
|
||||
case VER_NODE_PRIVATE:
|
||||
return "VER_NODE_PRIVATE";
|
||||
|
||||
case VER_ACCOUNT_ID:
|
||||
return "VER_ACCOUNT_ID";
|
||||
|
||||
case VER_ACCOUNT_PUBLIC:
|
||||
return "VER_ACCOUNT_PUBLIC";
|
||||
|
||||
case VER_ACCOUNT_PRIVATE:
|
||||
return "VER_ACCOUNT_PRIVATE";
|
||||
|
||||
case VER_FAMILY_GENERATOR:
|
||||
return "VER_FAMILY_GENERATOR";
|
||||
|
||||
case VER_FAMILY_SEED:
|
||||
return "VER_FAMILY_SEED";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
//
|
||||
// NodePublic
|
||||
//
|
||||
|
||||
RippleAddress RippleAddress::createNodePublic (const RippleAddress& naSeed)
|
||||
{
|
||||
CKey ckSeed (naSeed.getSeed ());
|
||||
RippleAddress naNew;
|
||||
|
||||
// YYY Should there be a GetPubKey() equiv that returns a uint256?
|
||||
naNew.setNodePublic (ckSeed.GetPubKey ());
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
RippleAddress RippleAddress::createNodePublic (Blob const& vPublic)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setNodePublic (vPublic);
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
RippleAddress RippleAddress::createNodePublic (const std::string& strPublic)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setNodePublic (strPublic);
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
uint160 RippleAddress::getNodeID () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - getNodeID");
|
||||
|
||||
case VER_NODE_PUBLIC:
|
||||
// Note, we are encoding the left.
|
||||
return Hash160 (vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
Blob const& RippleAddress::getNodePublic () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - getNodePublic");
|
||||
|
||||
case VER_NODE_PUBLIC:
|
||||
return vchData;
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
std::string RippleAddress::humanNodePublic () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - humanNodePublic");
|
||||
|
||||
case VER_NODE_PUBLIC:
|
||||
return ToString ();
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
bool RippleAddress::setNodePublic (const std::string& strPublic)
|
||||
{
|
||||
mIsValid = SetString (strPublic.c_str (), VER_NODE_PUBLIC);
|
||||
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
void RippleAddress::setNodePublic (Blob const& vPublic)
|
||||
{
|
||||
mIsValid = true;
|
||||
|
||||
SetData (VER_NODE_PUBLIC, vPublic);
|
||||
}
|
||||
|
||||
bool RippleAddress::verifyNodePublic (uint256 const& hash, Blob const& vchSig) const
|
||||
{
|
||||
CKey pubkey = CKey ();
|
||||
bool bVerified;
|
||||
|
||||
if (!pubkey.SetPubKey (getNodePublic ()))
|
||||
{
|
||||
// Failed to set public key.
|
||||
bVerified = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bVerified = pubkey.Verify (hash, vchSig);
|
||||
}
|
||||
|
||||
return bVerified;
|
||||
}
|
||||
|
||||
bool RippleAddress::verifyNodePublic (uint256 const& hash, const std::string& strSig) const
|
||||
{
|
||||
Blob vchSig (strSig.begin (), strSig.end ());
|
||||
|
||||
return verifyNodePublic (hash, vchSig);
|
||||
}
|
||||
|
||||
//
|
||||
// NodePrivate
|
||||
//
|
||||
|
||||
RippleAddress RippleAddress::createNodePrivate (const RippleAddress& naSeed)
|
||||
{
|
||||
uint256 uPrivKey;
|
||||
RippleAddress naNew;
|
||||
CKey ckSeed (naSeed.getSeed ());
|
||||
|
||||
ckSeed.GetPrivateKeyU (uPrivKey);
|
||||
|
||||
naNew.setNodePrivate (uPrivKey);
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
Blob const& RippleAddress::getNodePrivateData () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - getNodePrivateData");
|
||||
|
||||
case VER_NODE_PRIVATE:
|
||||
return vchData;
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
uint256 RippleAddress::getNodePrivate () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source = getNodePrivate");
|
||||
|
||||
case VER_NODE_PRIVATE:
|
||||
return uint256 (vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
std::string RippleAddress::humanNodePrivate () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - humanNodePrivate");
|
||||
|
||||
case VER_NODE_PRIVATE:
|
||||
return ToString ();
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
bool RippleAddress::setNodePrivate (const std::string& strPrivate)
|
||||
{
|
||||
mIsValid = SetString (strPrivate.c_str (), VER_NODE_PRIVATE);
|
||||
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
void RippleAddress::setNodePrivate (Blob const& vPrivate)
|
||||
{
|
||||
mIsValid = true;
|
||||
|
||||
SetData (VER_NODE_PRIVATE, vPrivate);
|
||||
}
|
||||
|
||||
void RippleAddress::setNodePrivate (uint256 hash256)
|
||||
{
|
||||
mIsValid = true;
|
||||
|
||||
SetData (VER_NODE_PRIVATE, hash256.begin (), 32);
|
||||
}
|
||||
|
||||
void RippleAddress::signNodePrivate (uint256 const& hash, Blob& vchSig) const
|
||||
{
|
||||
CKey ckPrivKey;
|
||||
|
||||
ckPrivKey.SetPrivateKeyU (getNodePrivate ());
|
||||
|
||||
if (!ckPrivKey.Sign (hash, vchSig))
|
||||
throw std::runtime_error ("Signing failed.");
|
||||
}
|
||||
|
||||
//
|
||||
// AccountID
|
||||
//
|
||||
|
||||
uint160 RippleAddress::getAccountID () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - getAccountID");
|
||||
|
||||
case VER_ACCOUNT_ID:
|
||||
return uint160 (vchData);
|
||||
|
||||
case VER_ACCOUNT_PUBLIC:
|
||||
// Note, we are encoding the left.
|
||||
return Hash160 (vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
typedef RippleMutex StaticLockType;
|
||||
typedef StaticLockType::ScopedLockType StaticScopedLockType;
|
||||
static StaticLockType s_lock ("RippleAddress", __FILE__, __LINE__);
|
||||
|
||||
static boost::unordered_map< Blob , std::string > rncMap;
|
||||
|
||||
std::string RippleAddress::humanAccountID () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - humanAccountID");
|
||||
|
||||
case VER_ACCOUNT_ID:
|
||||
{
|
||||
StaticScopedLockType sl (s_lock, __FILE__, __LINE__);
|
||||
boost::unordered_map< Blob , std::string >::iterator it = rncMap.find (vchData);
|
||||
|
||||
if (it != rncMap.end ())
|
||||
return it->second;
|
||||
|
||||
if (rncMap.size () > 10000)
|
||||
rncMap.clear ();
|
||||
|
||||
return rncMap[vchData] = ToString ();
|
||||
}
|
||||
|
||||
case VER_ACCOUNT_PUBLIC:
|
||||
{
|
||||
RippleAddress accountID;
|
||||
|
||||
(void) accountID.setAccountID (getAccountID ());
|
||||
|
||||
return accountID.ToString ();
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
bool RippleAddress::setAccountID (const std::string& strAccountID, const char* pAlphabet)
|
||||
{
|
||||
if (strAccountID.empty ())
|
||||
{
|
||||
setAccountID (uint160 ());
|
||||
|
||||
mIsValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsValid = SetString (strAccountID.c_str (), VER_ACCOUNT_ID, pAlphabet);
|
||||
}
|
||||
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
void RippleAddress::setAccountID (const uint160& hash160)
|
||||
{
|
||||
mIsValid = true;
|
||||
|
||||
SetData (VER_ACCOUNT_ID, hash160.begin (), 20);
|
||||
}
|
||||
|
||||
//
|
||||
// AccountPublic
|
||||
//
|
||||
|
||||
RippleAddress RippleAddress::createAccountPublic (const RippleAddress& naGenerator, int iSeq)
|
||||
{
|
||||
CKey ckPub (naGenerator, iSeq);
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setAccountPublic (ckPub.GetPubKey ());
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
Blob const& RippleAddress::getAccountPublic () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - getAccountPublic");
|
||||
|
||||
case VER_ACCOUNT_ID:
|
||||
throw std::runtime_error ("public not available from account id");
|
||||
break;
|
||||
|
||||
case VER_ACCOUNT_PUBLIC:
|
||||
return vchData;
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
std::string RippleAddress::humanAccountPublic () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - humanAccountPublic");
|
||||
|
||||
case VER_ACCOUNT_ID:
|
||||
throw std::runtime_error ("public not available from account id");
|
||||
|
||||
case VER_ACCOUNT_PUBLIC:
|
||||
return ToString ();
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
bool RippleAddress::setAccountPublic (const std::string& strPublic)
|
||||
{
|
||||
mIsValid = SetString (strPublic.c_str (), VER_ACCOUNT_PUBLIC);
|
||||
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
void RippleAddress::setAccountPublic (Blob const& vPublic)
|
||||
{
|
||||
mIsValid = true;
|
||||
|
||||
SetData (VER_ACCOUNT_PUBLIC, vPublic);
|
||||
}
|
||||
|
||||
void RippleAddress::setAccountPublic (const RippleAddress& generator, int seq)
|
||||
{
|
||||
CKey pubkey = CKey (generator, seq);
|
||||
|
||||
setAccountPublic (pubkey.GetPubKey ());
|
||||
}
|
||||
|
||||
bool RippleAddress::accountPublicVerify (uint256 const& uHash, Blob const& vucSig) const
|
||||
{
|
||||
CKey ckPublic;
|
||||
bool bVerified;
|
||||
|
||||
if (!ckPublic.SetPubKey (getAccountPublic ()))
|
||||
{
|
||||
// Bad private key.
|
||||
WriteLog (lsWARNING, RippleAddress) << "accountPublicVerify: Bad private key.";
|
||||
bVerified = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bVerified = ckPublic.Verify (uHash, vucSig);
|
||||
}
|
||||
|
||||
return bVerified;
|
||||
}
|
||||
|
||||
RippleAddress RippleAddress::createAccountID (const uint160& uiAccountID)
|
||||
{
|
||||
RippleAddress na;
|
||||
|
||||
na.setAccountID (uiAccountID);
|
||||
|
||||
return na;
|
||||
}
|
||||
|
||||
//
|
||||
// AccountPrivate
|
||||
//
|
||||
|
||||
RippleAddress RippleAddress::createAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int iSeq)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setAccountPrivate (naGenerator, naSeed, iSeq);
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
uint256 RippleAddress::getAccountPrivate () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - getAccountPrivate");
|
||||
|
||||
case VER_ACCOUNT_PRIVATE:
|
||||
return uint256 (vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
std::string RippleAddress::humanAccountPrivate () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - humanAccountPrivate");
|
||||
|
||||
case VER_ACCOUNT_PRIVATE:
|
||||
return ToString ();
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
bool RippleAddress::setAccountPrivate (const std::string& strPrivate)
|
||||
{
|
||||
mIsValid = SetString (strPrivate.c_str (), VER_ACCOUNT_PRIVATE);
|
||||
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
void RippleAddress::setAccountPrivate (Blob const& vPrivate)
|
||||
{
|
||||
mIsValid = true;
|
||||
|
||||
SetData (VER_ACCOUNT_PRIVATE, vPrivate);
|
||||
}
|
||||
|
||||
void RippleAddress::setAccountPrivate (uint256 hash256)
|
||||
{
|
||||
mIsValid = true;
|
||||
|
||||
SetData (VER_ACCOUNT_PRIVATE, hash256.begin (), 32);
|
||||
}
|
||||
|
||||
void RippleAddress::setAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq)
|
||||
{
|
||||
CKey ckPubkey = CKey (naSeed.getSeed ());
|
||||
CKey ckPrivkey = CKey (naGenerator, ckPubkey.GetSecretBN (), seq);
|
||||
uint256 uPrivKey;
|
||||
|
||||
ckPrivkey.GetPrivateKeyU (uPrivKey);
|
||||
|
||||
setAccountPrivate (uPrivKey);
|
||||
}
|
||||
|
||||
bool RippleAddress::accountPrivateSign (uint256 const& uHash, Blob& vucSig) const
|
||||
{
|
||||
CKey ckPrivate;
|
||||
bool bResult;
|
||||
|
||||
if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
|
||||
{
|
||||
// Bad private key.
|
||||
WriteLog (lsWARNING, RippleAddress) << "accountPrivateSign: Bad private key.";
|
||||
bResult = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bResult = ckPrivate.Sign (uHash, vucSig);
|
||||
CondLog (!bResult, lsWARNING, RippleAddress) << "accountPrivateSign: Signing failed.";
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool RippleAddress::accountPrivateVerify (uint256 const& uHash, Blob const& vucSig) const
|
||||
{
|
||||
CKey ckPrivate;
|
||||
bool bVerified;
|
||||
|
||||
if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
|
||||
{
|
||||
// Bad private key.
|
||||
WriteLog (lsWARNING, RippleAddress) << "accountPrivateVerify: Bad private key.";
|
||||
bVerified = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bVerified = ckPrivate.Verify (uHash, vucSig);
|
||||
}
|
||||
|
||||
return bVerified;
|
||||
}
|
||||
#endif
|
||||
|
||||
Blob RippleAddress::accountPrivateEncrypt (const RippleAddress& naPublicTo, Blob const& vucPlainText) const
|
||||
{
|
||||
CKey ckPrivate;
|
||||
CKey ckPublic;
|
||||
Blob vucCipherText;
|
||||
|
||||
if (!ckPublic.SetPubKey (naPublicTo.getAccountPublic ()))
|
||||
{
|
||||
// Bad public key.
|
||||
WriteLog (lsWARNING, RippleAddress) << "accountPrivateEncrypt: Bad public key.";
|
||||
}
|
||||
else if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
|
||||
{
|
||||
// Bad private key.
|
||||
WriteLog (lsWARNING, RippleAddress) << "accountPrivateEncrypt: Bad private key.";
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
vucCipherText = ckPrivate.encryptECIES (ckPublic, vucPlainText);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
nothing ();
|
||||
}
|
||||
}
|
||||
|
||||
return vucCipherText;
|
||||
}
|
||||
|
||||
Blob RippleAddress::accountPrivateDecrypt (const RippleAddress& naPublicFrom, Blob const& vucCipherText) const
|
||||
{
|
||||
CKey ckPrivate;
|
||||
CKey ckPublic;
|
||||
Blob vucPlainText;
|
||||
|
||||
if (!ckPublic.SetPubKey (naPublicFrom.getAccountPublic ()))
|
||||
{
|
||||
// Bad public key.
|
||||
WriteLog (lsWARNING, RippleAddress) << "accountPrivateDecrypt: Bad public key.";
|
||||
}
|
||||
else if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
|
||||
{
|
||||
// Bad private key.
|
||||
WriteLog (lsWARNING, RippleAddress) << "accountPrivateDecrypt: Bad private key.";
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
vucPlainText = ckPrivate.decryptECIES (ckPublic, vucCipherText);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
nothing ();
|
||||
}
|
||||
}
|
||||
|
||||
return vucPlainText;
|
||||
}
|
||||
|
||||
//
|
||||
// Generators
|
||||
//
|
||||
|
||||
BIGNUM* RippleAddress::getGeneratorBN () const
|
||||
{
|
||||
// returns the public generator
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - getGeneratorBN");
|
||||
|
||||
case VER_FAMILY_GENERATOR:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
|
||||
BIGNUM* ret = BN_bin2bn (&vchData[0], vchData.size (), NULL);
|
||||
assert (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Blob const& RippleAddress::getGenerator () const
|
||||
{
|
||||
// returns the public generator
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - getGenerator");
|
||||
|
||||
case VER_FAMILY_GENERATOR:
|
||||
// Do nothing.
|
||||
return vchData;
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
std::string RippleAddress::humanGenerator () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - humanGenerator");
|
||||
|
||||
case VER_FAMILY_GENERATOR:
|
||||
return ToString ();
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
bool RippleAddress::setGenerator (const std::string& strGenerator)
|
||||
{
|
||||
mIsValid = SetString (strGenerator.c_str (), VER_FAMILY_GENERATOR);
|
||||
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
void RippleAddress::setGenerator (Blob const& vPublic)
|
||||
{
|
||||
mIsValid = true;
|
||||
|
||||
SetData (VER_FAMILY_GENERATOR, vPublic);
|
||||
}
|
||||
|
||||
RippleAddress RippleAddress::createGeneratorPublic (const RippleAddress& naSeed)
|
||||
{
|
||||
CKey ckSeed (naSeed.getSeed ());
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setGenerator (ckSeed.GetPubKey ());
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
//
|
||||
// Seed
|
||||
//
|
||||
|
||||
uint128 RippleAddress::getSeed () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - getSeed");
|
||||
|
||||
case VER_FAMILY_SEED:
|
||||
return uint128 (vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
std::string RippleAddress::humanSeed1751 () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - humanSeed1751");
|
||||
|
||||
case VER_FAMILY_SEED:
|
||||
{
|
||||
std::string strHuman;
|
||||
std::string strLittle;
|
||||
std::string strBig;
|
||||
uint128 uSeed = getSeed ();
|
||||
|
||||
strLittle.assign (uSeed.begin (), uSeed.end ());
|
||||
|
||||
strBig.assign (strLittle.rbegin (), strLittle.rend ());
|
||||
|
||||
RFC1751::getEnglishFromKey (strHuman, strBig);
|
||||
|
||||
return strHuman;
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
std::string RippleAddress::humanSeed () const
|
||||
{
|
||||
switch (nVersion)
|
||||
{
|
||||
case VER_NONE:
|
||||
throw std::runtime_error ("unset source - humanSeed");
|
||||
|
||||
case VER_FAMILY_SEED:
|
||||
return ToString ();
|
||||
|
||||
default:
|
||||
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
int RippleAddress::setSeed1751 (const std::string& strHuman1751)
|
||||
{
|
||||
std::string strKey;
|
||||
int iResult = RFC1751::getKeyFromEnglish (strKey, strHuman1751);
|
||||
|
||||
if (1 == iResult)
|
||||
{
|
||||
Blob vchLittle (strKey.rbegin (), strKey.rend ());
|
||||
uint128 uSeed (vchLittle);
|
||||
|
||||
setSeed (uSeed);
|
||||
}
|
||||
|
||||
return iResult;
|
||||
}
|
||||
|
||||
bool RippleAddress::setSeed (const std::string& strSeed)
|
||||
{
|
||||
mIsValid = SetString (strSeed.c_str (), VER_FAMILY_SEED);
|
||||
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
bool RippleAddress::setSeedGeneric (const std::string& strText)
|
||||
{
|
||||
RippleAddress naTemp;
|
||||
bool bResult = true;
|
||||
uint128 uSeed;
|
||||
|
||||
if (strText.empty ()
|
||||
|| naTemp.setAccountID (strText)
|
||||
|| naTemp.setAccountPublic (strText)
|
||||
|| naTemp.setAccountPrivate (strText)
|
||||
|| naTemp.setNodePublic (strText)
|
||||
|| naTemp.setNodePrivate (strText))
|
||||
{
|
||||
bResult = false;
|
||||
}
|
||||
else if (strText.length () == 32 && uSeed.SetHex (strText, true))
|
||||
{
|
||||
setSeed (uSeed);
|
||||
}
|
||||
else if (setSeed (strText))
|
||||
{
|
||||
// Log::out() << "Recognized seed.";
|
||||
nothing ();
|
||||
}
|
||||
else if (1 == setSeed1751 (strText))
|
||||
{
|
||||
// Log::out() << "Recognized 1751 seed.";
|
||||
nothing ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log::out() << "Creating seed from pass phrase.";
|
||||
setSeed (CKey::PassPhraseToKey (strText));
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
void RippleAddress::setSeed (uint128 hash128)
|
||||
{
|
||||
mIsValid = true;
|
||||
|
||||
SetData (VER_FAMILY_SEED, hash128.begin (), 16);
|
||||
}
|
||||
|
||||
void RippleAddress::setSeedRandom ()
|
||||
{
|
||||
// XXX Maybe we should call MakeNewKey
|
||||
uint128 key;
|
||||
|
||||
RandomNumbers::getInstance ().fillBytes (key.begin (), key.size ());
|
||||
|
||||
RippleAddress::setSeed (key);
|
||||
}
|
||||
|
||||
RippleAddress RippleAddress::createSeedRandom ()
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setSeedRandom ();
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
RippleAddress RippleAddress::createSeedGeneric (const std::string& strText)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setSeedGeneric (strText);
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class RippleAddressTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
RippleAddressTests () : UnitTest ("RippleAddress", "ripple")
|
||||
{
|
||||
}
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
beginTestCase ("public/private");
|
||||
|
||||
// Construct a seed.
|
||||
RippleAddress naSeed;
|
||||
|
||||
expect (naSeed.setSeedGeneric ("masterpassphrase"));
|
||||
expect (naSeed.humanSeed () == "snoPBrXtMeMyMHUVTgbuqAfg1SUTb", naSeed.humanSeed ());
|
||||
|
||||
// Create node public/private key pair
|
||||
RippleAddress naNodePublic = RippleAddress::createNodePublic (naSeed);
|
||||
RippleAddress naNodePrivate = RippleAddress::createNodePrivate (naSeed);
|
||||
|
||||
expect (naNodePublic.humanNodePublic () == "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9", naNodePublic.humanNodePublic ());
|
||||
expect (naNodePrivate.humanNodePrivate () == "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe", naNodePrivate.humanNodePrivate ());
|
||||
|
||||
// Check node signing.
|
||||
Blob vucTextSrc = strCopy ("Hello, nurse!");
|
||||
uint256 uHash = Serializer::getSHA512Half (vucTextSrc);
|
||||
Blob vucTextSig;
|
||||
|
||||
naNodePrivate.signNodePrivate (uHash, vucTextSig);
|
||||
expect (naNodePublic.verifyNodePublic (uHash, vucTextSig), "Verify failed.");
|
||||
|
||||
// Construct a public generator from the seed.
|
||||
RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naSeed);
|
||||
|
||||
expect (naGenerator.humanGenerator () == "fhuJKrhSDzV2SkjLn9qbwm5AaRmrxDPfFsHDCP6yfDZWcxDFz4mt", naGenerator.humanGenerator ());
|
||||
|
||||
// Create account #0 public/private key pair.
|
||||
RippleAddress naAccountPublic0 = RippleAddress::createAccountPublic (naGenerator, 0);
|
||||
RippleAddress naAccountPrivate0 = RippleAddress::createAccountPrivate (naGenerator, naSeed, 0);
|
||||
|
||||
expect (naAccountPublic0.humanAccountID () == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", naAccountPublic0.humanAccountID ());
|
||||
expect (naAccountPublic0.humanAccountPublic () == "aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw", naAccountPublic0.humanAccountPublic ());
|
||||
expect (naAccountPrivate0.humanAccountPrivate () == "p9JfM6HHi64m6mvB6v5k7G2b1cXzGmYiCNJf6GHPKvFTWdeRVjh", naAccountPrivate0.humanAccountPrivate ());
|
||||
|
||||
// Create account #1 public/private key pair.
|
||||
RippleAddress naAccountPublic1 = RippleAddress::createAccountPublic (naGenerator, 1);
|
||||
RippleAddress naAccountPrivate1 = RippleAddress::createAccountPrivate (naGenerator, naSeed, 1);
|
||||
|
||||
expect (naAccountPublic1.humanAccountID () == "r4bYF7SLUMD7QgSLLpgJx38WJSY12ViRjP", naAccountPublic1.humanAccountID ());
|
||||
expect (naAccountPublic1.humanAccountPublic () == "aBPXpTfuLy1Bhk3HnGTTAqnovpKWQ23NpFMNkAF6F1Atg5vDyPrw", naAccountPublic1.humanAccountPublic ());
|
||||
expect (naAccountPrivate1.humanAccountPrivate () == "p9JEm822LMrzJii1k7TvdphfENTp6G5jr253Xa5rkzUWVr8ogQt", naAccountPrivate1.humanAccountPrivate ());
|
||||
|
||||
// Check account signing.
|
||||
expect (naAccountPrivate0.accountPrivateSign (uHash, vucTextSig), "Signing failed.");
|
||||
expect (naAccountPublic0.accountPublicVerify (uHash, vucTextSig), "Verify failed.");
|
||||
expect (!naAccountPublic1.accountPublicVerify (uHash, vucTextSig), "Anti-verify failed.");
|
||||
|
||||
expect (naAccountPrivate1.accountPrivateSign (uHash, vucTextSig), "Signing failed.");
|
||||
expect (naAccountPublic1.accountPublicVerify (uHash, vucTextSig), "Verify failed.");
|
||||
expect (!naAccountPublic0.accountPublicVerify (uHash, vucTextSig), "Anti-verify failed.");
|
||||
|
||||
// Check account encryption.
|
||||
Blob vucTextCipher
|
||||
= naAccountPrivate0.accountPrivateEncrypt (naAccountPublic1, vucTextSrc);
|
||||
Blob vucTextRecovered
|
||||
= naAccountPrivate1.accountPrivateDecrypt (naAccountPublic0, vucTextCipher);
|
||||
|
||||
expect (vucTextSrc == vucTextRecovered, "Encrypt-decrypt failed.");
|
||||
}
|
||||
};
|
||||
|
||||
static RippleAddressTests rippleAddressTests;
|
||||
208
src/ripple_data/protocol/ripple_RippleAddress.h
Normal file
208
src/ripple_data/protocol/ripple_RippleAddress.h
Normal file
@@ -0,0 +1,208 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_RIPPLEADDRESS_H
|
||||
#define RIPPLE_RIPPLEADDRESS_H
|
||||
|
||||
//
|
||||
// Used to hold addresses and parse and produce human formats.
|
||||
//
|
||||
// XXX This needs to be reworked to store data in uint160 and uint256. Conversion to CBase58Data should happen as needed.
|
||||
class RippleAddress : public CBase58Data
|
||||
{
|
||||
private:
|
||||
typedef enum
|
||||
{
|
||||
VER_NONE = 1,
|
||||
VER_NODE_PUBLIC = 28,
|
||||
VER_NODE_PRIVATE = 32,
|
||||
VER_ACCOUNT_ID = 0,
|
||||
VER_ACCOUNT_PUBLIC = 35,
|
||||
VER_ACCOUNT_PRIVATE = 34,
|
||||
VER_FAMILY_GENERATOR = 41,
|
||||
VER_FAMILY_SEED = 33,
|
||||
} VersionEncoding;
|
||||
|
||||
bool mIsValid;
|
||||
|
||||
public:
|
||||
RippleAddress ();
|
||||
|
||||
// For public and private key, checks if they are legal.
|
||||
bool isValid () const
|
||||
{
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
void clear ();
|
||||
bool isSet () const;
|
||||
|
||||
std::string humanAddressType () const;
|
||||
|
||||
//
|
||||
// Node Public - Also used for Validators
|
||||
//
|
||||
uint160 getNodeID () const;
|
||||
Blob const& getNodePublic () const;
|
||||
|
||||
std::string humanNodePublic () const;
|
||||
|
||||
bool setNodePublic (const std::string& strPublic);
|
||||
void setNodePublic (Blob const& vPublic);
|
||||
bool verifyNodePublic (uint256 const& hash, Blob const& vchSig) const;
|
||||
bool verifyNodePublic (uint256 const& hash, const std::string& strSig) const;
|
||||
|
||||
static RippleAddress createNodePublic (const RippleAddress& naSeed);
|
||||
static RippleAddress createNodePublic (Blob const& vPublic);
|
||||
static RippleAddress createNodePublic (const std::string& strPublic);
|
||||
|
||||
//
|
||||
// Node Private
|
||||
//
|
||||
Blob const& getNodePrivateData () const;
|
||||
uint256 getNodePrivate () const;
|
||||
|
||||
std::string humanNodePrivate () const;
|
||||
|
||||
bool setNodePrivate (const std::string& strPrivate);
|
||||
void setNodePrivate (Blob const& vPrivate);
|
||||
void setNodePrivate (uint256 hash256);
|
||||
void signNodePrivate (uint256 const& hash, Blob& vchSig) const;
|
||||
|
||||
static RippleAddress createNodePrivate (const RippleAddress& naSeed);
|
||||
|
||||
//
|
||||
// Accounts IDs
|
||||
//
|
||||
uint160 getAccountID () const;
|
||||
|
||||
std::string humanAccountID () const;
|
||||
|
||||
bool setAccountID (const std::string& strAccountID, const char* pAlphabet = Base58::getCurrentAlphabet ());
|
||||
void setAccountID (const uint160& hash160In);
|
||||
|
||||
static RippleAddress createAccountID (const std::string& strAccountID)
|
||||
{
|
||||
RippleAddress na;
|
||||
na.setAccountID (strAccountID);
|
||||
return na;
|
||||
}
|
||||
|
||||
static RippleAddress createAccountID (const uint160& uiAccountID);
|
||||
|
||||
static std::string createHumanAccountID (const uint160& uiAccountID)
|
||||
{
|
||||
return createAccountID (uiAccountID).humanAccountID ();
|
||||
}
|
||||
|
||||
static std::string createHumanAccountID (Blob const& vPrivate)
|
||||
{
|
||||
return createAccountPrivate (vPrivate).humanAccountID ();
|
||||
}
|
||||
|
||||
//
|
||||
// Accounts Public
|
||||
//
|
||||
Blob const& getAccountPublic () const;
|
||||
|
||||
std::string humanAccountPublic () const;
|
||||
|
||||
bool setAccountPublic (const std::string& strPublic);
|
||||
void setAccountPublic (Blob const& vPublic);
|
||||
void setAccountPublic (const RippleAddress& generator, int seq);
|
||||
|
||||
bool accountPublicVerify (uint256 const& uHash, Blob const& vucSig) const;
|
||||
|
||||
static RippleAddress createAccountPublic (Blob const& vPublic)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setAccountPublic (vPublic);
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
static std::string createHumanAccountPublic (Blob const& vPublic)
|
||||
{
|
||||
return createAccountPublic (vPublic).humanAccountPublic ();
|
||||
}
|
||||
|
||||
// Create a deterministic public key from a public generator.
|
||||
static RippleAddress createAccountPublic (const RippleAddress& naGenerator, int iSeq);
|
||||
|
||||
//
|
||||
// Accounts Private
|
||||
//
|
||||
uint256 getAccountPrivate () const;
|
||||
|
||||
std::string humanAccountPrivate () const;
|
||||
|
||||
bool setAccountPrivate (const std::string& strPrivate);
|
||||
void setAccountPrivate (Blob const& vPrivate);
|
||||
void setAccountPrivate (uint256 hash256);
|
||||
void setAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq);
|
||||
|
||||
bool accountPrivateSign (uint256 const& uHash, Blob& vucSig) const;
|
||||
// bool accountPrivateVerify(uint256 const& uHash, Blob const& vucSig) const;
|
||||
|
||||
// Encrypt a message.
|
||||
Blob accountPrivateEncrypt (const RippleAddress& naPublicTo, Blob const& vucPlainText) const;
|
||||
|
||||
// Decrypt a message.
|
||||
Blob accountPrivateDecrypt (const RippleAddress& naPublicFrom, Blob const& vucCipherText) const;
|
||||
|
||||
static RippleAddress createAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int iSeq);
|
||||
|
||||
static RippleAddress createAccountPrivate (Blob const& vPrivate)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setAccountPrivate (vPrivate);
|
||||
|
||||
return naNew;
|
||||
}
|
||||
|
||||
static std::string createHumanAccountPrivate (Blob const& vPrivate)
|
||||
{
|
||||
return createAccountPrivate (vPrivate).humanAccountPrivate ();
|
||||
}
|
||||
|
||||
//
|
||||
// Generators
|
||||
// Use to generate a master or regular family.
|
||||
//
|
||||
BIGNUM* getGeneratorBN () const; // DEPRECATED
|
||||
Blob const& getGenerator () const;
|
||||
|
||||
std::string humanGenerator () const;
|
||||
|
||||
bool setGenerator (const std::string& strGenerator);
|
||||
void setGenerator (Blob const& vPublic);
|
||||
// void setGenerator(const RippleAddress& seed);
|
||||
|
||||
// Create generator for making public deterministic keys.
|
||||
static RippleAddress createGeneratorPublic (const RippleAddress& naSeed);
|
||||
|
||||
//
|
||||
// Seeds
|
||||
// Clients must disallow reconizable entries from being seeds.
|
||||
uint128 getSeed () const;
|
||||
|
||||
std::string humanSeed () const;
|
||||
std::string humanSeed1751 () const;
|
||||
|
||||
bool setSeed (const std::string& strSeed);
|
||||
int setSeed1751 (const std::string& strHuman1751);
|
||||
bool setSeedGeneric (const std::string& strText);
|
||||
void setSeed (uint128 hash128);
|
||||
void setSeedRandom ();
|
||||
|
||||
static RippleAddress createSeedRandom ();
|
||||
static RippleAddress createSeedGeneric (const std::string& strText);
|
||||
};
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
47
src/ripple_data/protocol/ripple_RippleSystem.h
Normal file
47
src/ripple_data/protocol/ripple_RippleSystem.h
Normal file
@@ -0,0 +1,47 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_RIPPLESYSTEM_H
|
||||
#define RIPPLE_RIPPLESYSTEM_H
|
||||
|
||||
/** Protocol specific constant globals.
|
||||
*/
|
||||
// VFALCO NOTE use these from now on instead of the macros!!
|
||||
class RippleSystem
|
||||
{
|
||||
public:
|
||||
static inline char const* getSystemName ()
|
||||
{
|
||||
return "ripple";
|
||||
}
|
||||
|
||||
static char const* getCurrencyCode ()
|
||||
{
|
||||
return "XRP";
|
||||
}
|
||||
|
||||
static char const* getCurrencyCodeRipple ()
|
||||
{
|
||||
return "XRR";
|
||||
}
|
||||
|
||||
static int getCurrencyPrecision ()
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
};
|
||||
|
||||
// VFALCO TODO I would love to replace these macros with the language
|
||||
// constructs above. The problem is the way they are used at
|
||||
// the point of call, i.e. "User-agent:" SYSTEM_NAME
|
||||
// It will be necessary to rewrite some of them to use string streams.
|
||||
//
|
||||
#define SYSTEM_NAME "ripple"
|
||||
#define SYSTEM_CURRENCY_CODE "XRP"
|
||||
#define SYSTEM_CURRENCY_PRECISION 6
|
||||
#define SYSTEM_CURRENCY_CODE_RIPPLE "XRR"
|
||||
|
||||
#endif
|
||||
1924
src/ripple_data/protocol/ripple_STAmount.cpp
Normal file
1924
src/ripple_data/protocol/ripple_STAmount.cpp
Normal file
File diff suppressed because it is too large
Load Diff
300
src/ripple_data/protocol/ripple_STAmountRound.cpp
Normal file
300
src/ripple_data/protocol/ripple_STAmountRound.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
void STAmount::canonicalizeRound (bool isNative, uint64& value, int& offset, bool roundUp)
|
||||
{
|
||||
if (!roundUp) // canonicalize already rounds down
|
||||
return;
|
||||
|
||||
WriteLog (lsTRACE, STAmount) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down");
|
||||
|
||||
if (isNative)
|
||||
{
|
||||
if (offset < 0)
|
||||
{
|
||||
int loops = 0;
|
||||
|
||||
while (offset < -1)
|
||||
{
|
||||
value /= 10;
|
||||
++offset;
|
||||
++loops;
|
||||
}
|
||||
|
||||
value += (loops >= 2) ? 9 : 10; // add before last divide
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
else if (value > STAmount::cMaxValue)
|
||||
{
|
||||
while (value > (10 * STAmount::cMaxValue))
|
||||
{
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
|
||||
value += 9; // add before last divide
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
|
||||
WriteLog (lsTRACE, STAmount) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down");
|
||||
}
|
||||
|
||||
STAmount STAmount::addRound (const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
{
|
||||
v1.throwComparable (v2);
|
||||
|
||||
if (v2.mValue == 0)
|
||||
return v1;
|
||||
|
||||
if (v1.mValue == 0)
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative);
|
||||
|
||||
if (v1.mIsNative)
|
||||
return STAmount (v1.getFName (), v1.getSNValue () + v2.getSNValue ());
|
||||
|
||||
int ov1 = v1.mOffset, ov2 = v2.mOffset;
|
||||
int64 vv1 = static_cast<int64> (v1.mValue), vv2 = static_cast<uint64> (v2.mValue);
|
||||
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
|
||||
if (v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
|
||||
if (ov1 < ov2)
|
||||
{
|
||||
while (ov1 < (ov2 - 1))
|
||||
{
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
vv1 += 9;
|
||||
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (ov2 < ov1)
|
||||
{
|
||||
while (ov2 < (ov1 - 1))
|
||||
{
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
vv2 += 9;
|
||||
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
int64 fv = vv1 + vv2;
|
||||
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
|
||||
else if (fv >= 0)
|
||||
{
|
||||
uint64 v = static_cast<uint64> (fv);
|
||||
canonicalizeRound (false, v, ov1, roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 v = static_cast<uint64> (-fv);
|
||||
canonicalizeRound (false, v, ov1, !roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
|
||||
}
|
||||
}
|
||||
|
||||
STAmount STAmount::subRound (const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
{
|
||||
v1.throwComparable (v2);
|
||||
|
||||
if (v2.mValue == 0)
|
||||
return v1;
|
||||
|
||||
if (v1.mValue == 0)
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, !v2.mIsNegative);
|
||||
|
||||
if (v1.mIsNative)
|
||||
return STAmount (v1.getFName (), v1.getSNValue () - v2.getSNValue ());
|
||||
|
||||
int ov1 = v1.mOffset, ov2 = v2.mOffset;
|
||||
int64 vv1 = static_cast<int64> (v1.mValue), vv2 = static_cast<uint64> (v2.mValue);
|
||||
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
|
||||
if (!v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
|
||||
if (ov1 < ov2)
|
||||
{
|
||||
while (ov1 < (ov2 - 1))
|
||||
{
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
vv1 += 9;
|
||||
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (ov2 < ov1)
|
||||
{
|
||||
while (ov2 < (ov1 - 1))
|
||||
{
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
vv2 += 9;
|
||||
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
int64 fv = vv1 + vv2;
|
||||
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
|
||||
else if (fv >= 0)
|
||||
{
|
||||
uint64 v = static_cast<uint64> (fv);
|
||||
canonicalizeRound (false, v, ov1, roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 v = static_cast<uint64> (-fv);
|
||||
canonicalizeRound (false, v, ov1, !roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
|
||||
}
|
||||
}
|
||||
|
||||
STAmount STAmount::mulRound (const STAmount& v1, const STAmount& v2,
|
||||
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
|
||||
{
|
||||
if (v1.isZero () || v2.isZero ())
|
||||
return STAmount (uCurrencyID, uIssuerID);
|
||||
|
||||
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ())
|
||||
{
|
||||
uint64 minV = (v1.getSNValue () < v2.getSNValue ()) ? v1.getSNValue () : v2.getSNValue ();
|
||||
uint64 maxV = (v1.getSNValue () < v2.getSNValue ()) ? v2.getSNValue () : v1.getSNValue ();
|
||||
|
||||
if (minV > 3000000000ull) // sqrt(cMaxNative)
|
||||
throw std::runtime_error ("Native value overflow");
|
||||
|
||||
if (((maxV >> 32) * minV) > 2095475792ull) // cMaxNative / 2^32
|
||||
throw std::runtime_error ("Native value overflow");
|
||||
|
||||
return STAmount (v1.getFName (), minV * maxV);
|
||||
}
|
||||
|
||||
uint64 value1 = v1.mValue, value2 = v2.mValue;
|
||||
int offset1 = v1.mOffset, offset2 = v2.mOffset;
|
||||
|
||||
if (v1.mIsNative)
|
||||
{
|
||||
while (value1 < STAmount::cMinValue)
|
||||
{
|
||||
value1 *= 10;
|
||||
--offset1;
|
||||
}
|
||||
}
|
||||
|
||||
if (v2.mIsNative)
|
||||
{
|
||||
while (value2 < STAmount::cMinValue)
|
||||
{
|
||||
value2 *= 10;
|
||||
--offset2;
|
||||
}
|
||||
}
|
||||
|
||||
bool resultNegative = v1.mIsNegative != v2.mIsNegative;
|
||||
// Compute (numerator * denominator) / 10^14 with rounding
|
||||
// 10^16 <= result <= 10^18
|
||||
CBigNum v;
|
||||
|
||||
if ((BN_add_word64 (&v, value1) != 1) || (BN_mul_word64 (&v, value2) != 1))
|
||||
throw std::runtime_error ("internal bn error");
|
||||
|
||||
if (resultNegative != roundUp) // rounding down is automatic when we divide
|
||||
BN_add_word64 (&v, tenTo14m1);
|
||||
|
||||
if (BN_div_word64 (&v, tenTo14) == ((uint64) - 1))
|
||||
throw std::runtime_error ("internal bn error");
|
||||
|
||||
// 10^16 <= product <= 10^18
|
||||
assert (BN_num_bytes (&v) <= 64);
|
||||
|
||||
uint64 amount = v.getuint64 ();
|
||||
int offset = offset1 + offset2 + 14;
|
||||
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
|
||||
return STAmount (uCurrencyID, uIssuerID, amount, offset, resultNegative);
|
||||
}
|
||||
|
||||
STAmount STAmount::divRound (const STAmount& num, const STAmount& den,
|
||||
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
|
||||
{
|
||||
if (den.isZero ())
|
||||
throw std::runtime_error ("division by zero");
|
||||
|
||||
if (num.isZero ())
|
||||
return STAmount (uCurrencyID, uIssuerID);
|
||||
|
||||
uint64 numVal = num.mValue, denVal = den.mValue;
|
||||
int numOffset = num.mOffset, denOffset = den.mOffset;
|
||||
|
||||
if (num.mIsNative)
|
||||
while (numVal < STAmount::cMinValue)
|
||||
{
|
||||
// Need to bring into range
|
||||
numVal *= 10;
|
||||
--numOffset;
|
||||
}
|
||||
|
||||
if (den.mIsNative)
|
||||
while (denVal < STAmount::cMinValue)
|
||||
{
|
||||
denVal *= 10;
|
||||
--denOffset;
|
||||
}
|
||||
|
||||
bool resultNegative = num.mIsNegative != den.mIsNegative;
|
||||
// Compute (numerator * 10^17) / denominator
|
||||
CBigNum v;
|
||||
|
||||
if ((BN_add_word64 (&v, numVal) != 1) || (BN_mul_word64 (&v, tenTo17) != 1))
|
||||
throw std::runtime_error ("internal bn error");
|
||||
|
||||
if (resultNegative != roundUp) // Rounding down is automatic when we divide
|
||||
BN_add_word64 (&v, denVal - 1);
|
||||
|
||||
if (BN_div_word64 (&v, denVal) == ((uint64) - 1))
|
||||
throw std::runtime_error ("internal bn error");
|
||||
|
||||
// 10^16 <= quotient <= 10^18
|
||||
assert (BN_num_bytes (&v) <= 64);
|
||||
|
||||
uint64 amount = v.getuint64 ();
|
||||
int offset = numOffset - denOffset - 17;
|
||||
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
|
||||
return STAmount (uCurrencyID, uIssuerID, amount, offset, resultNegative);
|
||||
}
|
||||
|
||||
186
src/ripple_data/protocol/ripple_SerializeDeclarations.h
Normal file
186
src/ripple_data/protocol/ripple_SerializeDeclarations.h
Normal file
@@ -0,0 +1,186 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// This is not really a header file, but it can be used as one with
|
||||
// appropriate #define statements.
|
||||
|
||||
/*
|
||||
Common type common field - 1 byte
|
||||
Common type uncommon field - 2 bytes
|
||||
...
|
||||
|
||||
Rarity of fields determines the number of bytes.
|
||||
This is done to reduce the average size of the messages.
|
||||
*/
|
||||
|
||||
// types (common)
|
||||
TYPE (Int16, UINT16, 1)
|
||||
TYPE (Int32, UINT32, 2)
|
||||
TYPE (Int64, UINT64, 3)
|
||||
TYPE (Hash128, HASH128, 4)
|
||||
TYPE (Hash256, HASH256, 5)
|
||||
TYPE (Amount, AMOUNT, 6)
|
||||
TYPE (VariableLength, VL, 7)
|
||||
TYPE (Account, ACCOUNT, 8)
|
||||
// 9-13 are reserved
|
||||
TYPE (Object, OBJECT, 14)
|
||||
TYPE (Array, ARRAY, 15)
|
||||
|
||||
// types (uncommon)
|
||||
TYPE (Int8, UINT8, 16)
|
||||
TYPE (Hash160, HASH160, 17)
|
||||
TYPE (PathSet, PATHSET, 18)
|
||||
TYPE (Vector256, VECTOR256, 19)
|
||||
|
||||
|
||||
|
||||
// 8-bit integers
|
||||
FIELD (CloseResolution, UINT8, 1)
|
||||
FIELD (TemplateEntryType, UINT8, 2)
|
||||
FIELD (TransactionResult, UINT8, 3)
|
||||
|
||||
// 16-bit integers
|
||||
FIELD (LedgerEntryType, UINT16, 1)
|
||||
FIELD (TransactionType, UINT16, 2)
|
||||
|
||||
// 32-bit integers (common)
|
||||
FIELD (Flags, UINT32, 2)
|
||||
FIELD (SourceTag, UINT32, 3)
|
||||
FIELD (Sequence, UINT32, 4)
|
||||
FIELD (PreviousTxnLgrSeq, UINT32, 5)
|
||||
FIELD (LedgerSequence, UINT32, 6)
|
||||
FIELD (CloseTime, UINT32, 7)
|
||||
FIELD (ParentCloseTime, UINT32, 8)
|
||||
FIELD (SigningTime, UINT32, 9)
|
||||
FIELD (Expiration, UINT32, 10)
|
||||
FIELD (TransferRate, UINT32, 11)
|
||||
FIELD (WalletSize, UINT32, 12)
|
||||
FIELD (OwnerCount, UINT32, 13)
|
||||
FIELD (DestinationTag, UINT32, 14)
|
||||
|
||||
// 32-bit integers (uncommon)
|
||||
FIELD (HighQualityIn, UINT32, 16)
|
||||
FIELD (HighQualityOut, UINT32, 17)
|
||||
FIELD (LowQualityIn, UINT32, 18)
|
||||
FIELD (LowQualityOut, UINT32, 19)
|
||||
FIELD (QualityIn, UINT32, 20)
|
||||
FIELD (QualityOut, UINT32, 21)
|
||||
FIELD (StampEscrow, UINT32, 22)
|
||||
FIELD (BondAmount, UINT32, 23)
|
||||
FIELD (LoadFee, UINT32, 24)
|
||||
FIELD (OfferSequence, UINT32, 25)
|
||||
FIELD (FirstLedgerSequence, UINT32, 26) // Deprecated: do not use
|
||||
FIELD (LastLedgerSequence, UINT32, 27)
|
||||
FIELD (TransactionIndex, UINT32, 28)
|
||||
FIELD (OperationLimit, UINT32, 29)
|
||||
FIELD (ReferenceFeeUnits, UINT32, 30)
|
||||
FIELD (ReserveBase, UINT32, 31)
|
||||
FIELD (ReserveIncrement, UINT32, 32)
|
||||
FIELD (SetFlag, UINT32, 33)
|
||||
FIELD (ClearFlag, UINT32, 34)
|
||||
|
||||
// 64-bit integers
|
||||
FIELD (IndexNext, UINT64, 1)
|
||||
FIELD (IndexPrevious, UINT64, 2)
|
||||
FIELD (BookNode, UINT64, 3)
|
||||
FIELD (OwnerNode, UINT64, 4)
|
||||
FIELD (BaseFee, UINT64, 5)
|
||||
FIELD (ExchangeRate, UINT64, 6)
|
||||
FIELD (LowNode, UINT64, 7)
|
||||
FIELD (HighNode, UINT64, 8)
|
||||
|
||||
|
||||
// 128-bit
|
||||
FIELD (EmailHash, HASH128, 1)
|
||||
|
||||
// 256-bit (common)
|
||||
FIELD (LedgerHash, HASH256, 1)
|
||||
FIELD (ParentHash, HASH256, 2)
|
||||
FIELD (TransactionHash, HASH256, 3)
|
||||
FIELD (AccountHash, HASH256, 4)
|
||||
FIELD (PreviousTxnID, HASH256, 5)
|
||||
FIELD (LedgerIndex, HASH256, 6)
|
||||
FIELD (WalletLocator, HASH256, 7)
|
||||
FIELD (RootIndex, HASH256, 8)
|
||||
|
||||
// 256-bit (uncommon)
|
||||
FIELD (BookDirectory, HASH256, 16)
|
||||
FIELD (InvoiceID, HASH256, 17)
|
||||
FIELD (Nickname, HASH256, 18)
|
||||
FIELD (Feature, HASH256, 19)
|
||||
|
||||
// 160-bit (common)
|
||||
FIELD (TakerPaysCurrency, HASH160, 1)
|
||||
FIELD (TakerPaysIssuer, HASH160, 2)
|
||||
FIELD (TakerGetsCurrency, HASH160, 3)
|
||||
FIELD (TakerGetsIssuer, HASH160, 4)
|
||||
|
||||
// currency amount (common)
|
||||
FIELD (Amount, AMOUNT, 1)
|
||||
FIELD (Balance, AMOUNT, 2)
|
||||
FIELD (LimitAmount, AMOUNT, 3)
|
||||
FIELD (TakerPays, AMOUNT, 4)
|
||||
FIELD (TakerGets, AMOUNT, 5)
|
||||
FIELD (LowLimit, AMOUNT, 6)
|
||||
FIELD (HighLimit, AMOUNT, 7)
|
||||
FIELD (Fee, AMOUNT, 8)
|
||||
FIELD (SendMax, AMOUNT, 9)
|
||||
|
||||
// currency amount (uncommon)
|
||||
FIELD (MinimumOffer, AMOUNT, 16)
|
||||
FIELD (RippleEscrow, AMOUNT, 17)
|
||||
|
||||
// variable length
|
||||
FIELD (PublicKey, VL, 1)
|
||||
FIELD (MessageKey, VL, 2)
|
||||
FIELD (SigningPubKey, VL, 3)
|
||||
FIELD (TxnSignature, VL, 4)
|
||||
FIELD (Generator, VL, 5)
|
||||
FIELD (Signature, VL, 6)
|
||||
FIELD (Domain, VL, 7)
|
||||
FIELD (FundCode, VL, 8)
|
||||
FIELD (RemoveCode, VL, 9)
|
||||
FIELD (ExpireCode, VL, 10)
|
||||
FIELD (CreateCode, VL, 11)
|
||||
|
||||
// account
|
||||
FIELD (Account, ACCOUNT, 1)
|
||||
FIELD (Owner, ACCOUNT, 2)
|
||||
FIELD (Destination, ACCOUNT, 3)
|
||||
FIELD (Issuer, ACCOUNT, 4)
|
||||
FIELD (Target, ACCOUNT, 7)
|
||||
FIELD (RegularKey, ACCOUNT, 8)
|
||||
|
||||
// path set
|
||||
FIELD (Paths, PATHSET, 1)
|
||||
|
||||
// vector of 256-bit
|
||||
FIELD (Indexes, VECTOR256, 1)
|
||||
FIELD (Hashes, VECTOR256, 2)
|
||||
FIELD (Features, VECTOR256, 3)
|
||||
|
||||
// inner object
|
||||
// OBJECT/1 is reserved for end of object
|
||||
FIELD (TransactionMetaData, OBJECT, 2)
|
||||
FIELD (CreatedNode, OBJECT, 3)
|
||||
FIELD (DeletedNode, OBJECT, 4)
|
||||
FIELD (ModifiedNode, OBJECT, 5)
|
||||
FIELD (PreviousFields, OBJECT, 6)
|
||||
FIELD (FinalFields, OBJECT, 7)
|
||||
FIELD (NewFields, OBJECT, 8)
|
||||
FIELD (TemplateEntry, OBJECT, 9)
|
||||
|
||||
// array of objects
|
||||
// ARRAY/1 is reserved for end of array
|
||||
FIELD (SigningAccounts, ARRAY, 2)
|
||||
FIELD (TxnSignatures, ARRAY, 3)
|
||||
FIELD (Signatures, ARRAY, 4)
|
||||
FIELD (Template, ARRAY, 5)
|
||||
FIELD (Necessary, ARRAY, 6)
|
||||
FIELD (Sufficient, ARRAY, 7)
|
||||
FIELD (AffectedNodes, ARRAY, 8)
|
||||
|
||||
// vim:ts=4
|
||||
1654
src/ripple_data/protocol/ripple_SerializedObject.cpp
Normal file
1654
src/ripple_data/protocol/ripple_SerializedObject.cpp
Normal file
File diff suppressed because it is too large
Load Diff
510
src/ripple_data/protocol/ripple_SerializedObject.h
Normal file
510
src/ripple_data/protocol/ripple_SerializedObject.h
Normal file
@@ -0,0 +1,510 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_SERIALIZEDOBJECT_H
|
||||
#define RIPPLE_SERIALIZEDOBJECT_H
|
||||
|
||||
class STObject
|
||||
: public SerializedType
|
||||
, public CountedObject <STObject>
|
||||
{
|
||||
public:
|
||||
static char const* getCountedObjectName () { return "STObject"; }
|
||||
|
||||
STObject () : mType (NULL)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
explicit STObject (SField::ref name) : SerializedType (name), mType (NULL)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
STObject (const SOTemplate & type, SField::ref name) : SerializedType (name)
|
||||
{
|
||||
set (type);
|
||||
}
|
||||
|
||||
STObject (const SOTemplate & type, SerializerIterator & sit, SField::ref name) : SerializedType (name)
|
||||
{
|
||||
set (sit);
|
||||
setType (type);
|
||||
}
|
||||
|
||||
UPTR_T<STObject> oClone () const
|
||||
{
|
||||
return UPTR_T<STObject> (new STObject (*this));
|
||||
}
|
||||
|
||||
static UPTR_T<STObject> parseJson (const Json::Value & value, SField::ref name = sfGeneric, int depth = 0);
|
||||
|
||||
virtual ~STObject ()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static UPTR_T<SerializedType> deserialize (SerializerIterator & sit, SField::ref name);
|
||||
|
||||
bool setType (const SOTemplate & type);
|
||||
bool isValidForType ();
|
||||
bool isFieldAllowed (SField::ref);
|
||||
bool isFree () const
|
||||
{
|
||||
return mType == NULL;
|
||||
}
|
||||
|
||||
void set (const SOTemplate&);
|
||||
bool set (SerializerIterator & u, int depth = 0);
|
||||
|
||||
virtual SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_OBJECT;
|
||||
}
|
||||
virtual bool isEquivalent (const SerializedType & t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return mData.empty ();
|
||||
}
|
||||
|
||||
virtual void add (Serializer & s) const
|
||||
{
|
||||
add (s, true); // just inner elements
|
||||
}
|
||||
|
||||
void add (Serializer & s, bool withSignature) const;
|
||||
|
||||
// VFALCO NOTE does this return an expensive copy of an object with a dynamic buffer?
|
||||
// VFALCO TODO Remove this function and fix the few callers.
|
||||
Serializer getSerializer () const
|
||||
{
|
||||
Serializer s;
|
||||
add (s);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string getFullText () const;
|
||||
std::string getText () const;
|
||||
virtual Json::Value getJson (int options) const;
|
||||
|
||||
int addObject (const SerializedType & t)
|
||||
{
|
||||
mData.push_back (t.clone ().release ());
|
||||
return mData.size () - 1;
|
||||
}
|
||||
int giveObject (UPTR_T<SerializedType> t)
|
||||
{
|
||||
mData.push_back (t.release ());
|
||||
return mData.size () - 1;
|
||||
}
|
||||
int giveObject (SerializedType * t)
|
||||
{
|
||||
mData.push_back (t);
|
||||
return mData.size () - 1;
|
||||
}
|
||||
const boost::ptr_vector<SerializedType>& peekData () const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
boost::ptr_vector<SerializedType>& peekData ()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
SerializedType& front ()
|
||||
{
|
||||
return mData.front ();
|
||||
}
|
||||
const SerializedType& front () const
|
||||
{
|
||||
return mData.front ();
|
||||
}
|
||||
SerializedType& back ()
|
||||
{
|
||||
return mData.back ();
|
||||
}
|
||||
const SerializedType& back () const
|
||||
{
|
||||
return mData.back ();
|
||||
}
|
||||
|
||||
int getCount () const
|
||||
{
|
||||
return mData.size ();
|
||||
}
|
||||
|
||||
bool setFlag (uint32);
|
||||
bool clearFlag (uint32);
|
||||
bool isFlag(uint32);
|
||||
uint32 getFlags () const;
|
||||
|
||||
uint256 getHash (uint32 prefix) const;
|
||||
uint256 getSigningHash (uint32 prefix) const;
|
||||
|
||||
const SerializedType& peekAtIndex (int offset) const
|
||||
{
|
||||
return mData[offset];
|
||||
}
|
||||
SerializedType& getIndex (int offset)
|
||||
{
|
||||
return mData[offset];
|
||||
}
|
||||
const SerializedType* peekAtPIndex (int offset) const
|
||||
{
|
||||
return & (mData[offset]);
|
||||
}
|
||||
SerializedType* getPIndex (int offset)
|
||||
{
|
||||
return & (mData[offset]);
|
||||
}
|
||||
|
||||
int getFieldIndex (SField::ref field) const;
|
||||
SField::ref getFieldSType (int index) const;
|
||||
|
||||
const SerializedType& peekAtField (SField::ref field) const;
|
||||
SerializedType& getField (SField::ref field);
|
||||
const SerializedType* peekAtPField (SField::ref field) const;
|
||||
SerializedType* getPField (SField::ref field, bool createOkay = false);
|
||||
|
||||
// these throw if the field type doesn't match, or return default values if the
|
||||
// field is optional but not present
|
||||
std::string getFieldString (SField::ref field) const;
|
||||
unsigned char getFieldU8 (SField::ref field) const;
|
||||
uint16 getFieldU16 (SField::ref field) const;
|
||||
uint32 getFieldU32 (SField::ref field) const;
|
||||
uint64 getFieldU64 (SField::ref field) const;
|
||||
uint128 getFieldH128 (SField::ref field) const;
|
||||
uint160 getFieldH160 (SField::ref field) const;
|
||||
uint256 getFieldH256 (SField::ref field) const;
|
||||
RippleAddress getFieldAccount (SField::ref field) const;
|
||||
uint160 getFieldAccount160 (SField::ref field) const;
|
||||
Blob getFieldVL (SField::ref field) const;
|
||||
const STAmount& getFieldAmount (SField::ref field) const;
|
||||
const STPathSet& getFieldPathSet (SField::ref field) const;
|
||||
const STVector256& getFieldV256 (SField::ref field) const;
|
||||
|
||||
void setFieldU8 (SField::ref field, unsigned char);
|
||||
void setFieldU16 (SField::ref field, uint16);
|
||||
void setFieldU32 (SField::ref field, uint32);
|
||||
void setFieldU64 (SField::ref field, uint64);
|
||||
void setFieldH128 (SField::ref field, const uint128&);
|
||||
void setFieldH160 (SField::ref field, const uint160&);
|
||||
void setFieldH256 (SField::ref field, uint256 const& );
|
||||
void setFieldVL (SField::ref field, Blob const&);
|
||||
void setFieldAccount (SField::ref field, const uint160&);
|
||||
void setFieldAccount (SField::ref field, const RippleAddress & addr)
|
||||
{
|
||||
setFieldAccount (field, addr.getAccountID ());
|
||||
}
|
||||
void setFieldAmount (SField::ref field, const STAmount&);
|
||||
void setFieldPathSet (SField::ref field, const STPathSet&);
|
||||
void setFieldV256 (SField::ref field, const STVector256 & v);
|
||||
|
||||
STObject& peekFieldObject (SField::ref field);
|
||||
|
||||
bool isFieldPresent (SField::ref field) const;
|
||||
SerializedType* makeFieldPresent (SField::ref field);
|
||||
void makeFieldAbsent (SField::ref field);
|
||||
bool delField (SField::ref field);
|
||||
void delField (int index);
|
||||
|
||||
static UPTR_T <SerializedType> makeDefaultObject (SerializedTypeID id, SField::ref name);
|
||||
|
||||
// VFALCO TODO remove the 'depth' parameter
|
||||
static UPTR_T<SerializedType> makeDeserializedObject (
|
||||
SerializedTypeID id,
|
||||
SField::ref name,
|
||||
SerializerIterator&,
|
||||
int depth);
|
||||
|
||||
static UPTR_T<SerializedType> makeNonPresentObject (SField::ref name)
|
||||
{
|
||||
return makeDefaultObject (STI_NOTPRESENT, name);
|
||||
}
|
||||
|
||||
static UPTR_T<SerializedType> makeDefaultObject (SField::ref name)
|
||||
{
|
||||
return makeDefaultObject (name.fieldType, name);
|
||||
}
|
||||
|
||||
// field iterator stuff
|
||||
typedef boost::ptr_vector<SerializedType>::iterator iterator;
|
||||
typedef boost::ptr_vector<SerializedType>::const_iterator const_iterator;
|
||||
iterator begin ()
|
||||
{
|
||||
return mData.begin ();
|
||||
}
|
||||
iterator end ()
|
||||
{
|
||||
return mData.end ();
|
||||
}
|
||||
const_iterator begin () const
|
||||
{
|
||||
return mData.begin ();
|
||||
}
|
||||
const_iterator end () const
|
||||
{
|
||||
return mData.end ();
|
||||
}
|
||||
bool empty () const
|
||||
{
|
||||
return mData.empty ();
|
||||
}
|
||||
|
||||
bool hasMatchingEntry (const SerializedType&);
|
||||
|
||||
bool operator== (const STObject & o) const;
|
||||
bool operator!= (const STObject & o) const
|
||||
{
|
||||
return ! (*this == o);
|
||||
}
|
||||
|
||||
private:
|
||||
/** Returns a value or throws if out of range.
|
||||
|
||||
This will throw if the source value cannot be represented
|
||||
within the destination type.
|
||||
*/
|
||||
// VFALCO NOTE This won't work right
|
||||
/*
|
||||
template <class T, class U>
|
||||
static T getWithRangeCheck (U v)
|
||||
{
|
||||
if (v < std::numeric_limits <T>::min ()) ||
|
||||
v > std::numeric_limits <T>::max ())
|
||||
{
|
||||
throw std::runtime_error ("Value out of range");
|
||||
}
|
||||
|
||||
return static_cast <T> (v);
|
||||
}
|
||||
*/
|
||||
|
||||
// VFALCO TODO these parameters should not be const references.
|
||||
template <typename T, typename U>
|
||||
static T range_check_cast (const U& value, const T& minimum, const T& maximum)
|
||||
{
|
||||
if ((value < minimum) || (value > maximum))
|
||||
throw std::runtime_error ("Value out of range");
|
||||
|
||||
return static_cast<T> (value);
|
||||
}
|
||||
|
||||
STObject* duplicate () const
|
||||
{
|
||||
return new STObject (*this);
|
||||
}
|
||||
|
||||
STObject (SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType (name), mType (NULL)
|
||||
{
|
||||
mData.swap (data);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::ptr_vector<SerializedType> mData;
|
||||
const SOTemplate* mType;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline STObject::iterator range_begin (STObject& x)
|
||||
{
|
||||
return x.begin ();
|
||||
}
|
||||
inline STObject::iterator range_end (STObject& x)
|
||||
{
|
||||
return x.end ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class STArray
|
||||
: public SerializedType
|
||||
, public CountedObject <STArray>
|
||||
{
|
||||
public:
|
||||
static char const* getCountedObjectName () { return "STArray"; }
|
||||
|
||||
typedef boost::ptr_vector<STObject> vector;
|
||||
typedef boost::ptr_vector<STObject>::iterator iterator;
|
||||
typedef boost::ptr_vector<STObject>::const_iterator const_iterator;
|
||||
typedef boost::ptr_vector<STObject>::reverse_iterator reverse_iterator;
|
||||
typedef boost::ptr_vector<STObject>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef boost::ptr_vector<STObject>::size_type size_type;
|
||||
|
||||
public:
|
||||
STArray ()
|
||||
{
|
||||
;
|
||||
}
|
||||
explicit STArray (int n)
|
||||
{
|
||||
value.reserve (n);
|
||||
}
|
||||
explicit STArray (SField::ref f) : SerializedType (f)
|
||||
{
|
||||
;
|
||||
}
|
||||
STArray (SField::ref f, int n) : SerializedType (f)
|
||||
{
|
||||
value.reserve (n);
|
||||
}
|
||||
STArray (SField::ref f, const vector & v) : SerializedType (f), value (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
explicit STArray (vector & v) : value (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static UPTR_T<SerializedType> deserialize (SerializerIterator & sit, SField::ref name)
|
||||
{
|
||||
return UPTR_T<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
const vector& getValue () const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
vector& getValue ()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
// VFALCO NOTE as long as we're married to boost why not use boost::iterator_facade?
|
||||
//
|
||||
// vector-like functions
|
||||
void push_back (const STObject & object)
|
||||
{
|
||||
value.push_back (object.oClone ().release ());
|
||||
}
|
||||
STObject& operator[] (int j)
|
||||
{
|
||||
return value[j];
|
||||
}
|
||||
const STObject& operator[] (int j) const
|
||||
{
|
||||
return value[j];
|
||||
}
|
||||
iterator begin ()
|
||||
{
|
||||
return value.begin ();
|
||||
}
|
||||
const_iterator begin () const
|
||||
{
|
||||
return value.begin ();
|
||||
}
|
||||
iterator end ()
|
||||
{
|
||||
return value.end ();
|
||||
}
|
||||
const_iterator end () const
|
||||
{
|
||||
return value.end ();
|
||||
}
|
||||
size_type size () const
|
||||
{
|
||||
return value.size ();
|
||||
}
|
||||
reverse_iterator rbegin ()
|
||||
{
|
||||
return value.rbegin ();
|
||||
}
|
||||
const_reverse_iterator rbegin () const
|
||||
{
|
||||
return value.rbegin ();
|
||||
}
|
||||
reverse_iterator rend ()
|
||||
{
|
||||
return value.rend ();
|
||||
}
|
||||
const_reverse_iterator rend () const
|
||||
{
|
||||
return value.rend ();
|
||||
}
|
||||
iterator erase (iterator pos)
|
||||
{
|
||||
return value.erase (pos);
|
||||
}
|
||||
STObject& front ()
|
||||
{
|
||||
return value.front ();
|
||||
}
|
||||
const STObject& front () const
|
||||
{
|
||||
return value.front ();
|
||||
}
|
||||
STObject& back ()
|
||||
{
|
||||
return value.back ();
|
||||
}
|
||||
const STObject& back () const
|
||||
{
|
||||
return value.back ();
|
||||
}
|
||||
void pop_back ()
|
||||
{
|
||||
value.pop_back ();
|
||||
}
|
||||
bool empty () const
|
||||
{
|
||||
return value.empty ();
|
||||
}
|
||||
void clear ()
|
||||
{
|
||||
value.clear ();
|
||||
}
|
||||
void swap (STArray & a)
|
||||
{
|
||||
value.swap (a.value);
|
||||
}
|
||||
|
||||
virtual std::string getFullText () const;
|
||||
virtual std::string getText () const;
|
||||
virtual Json::Value getJson (int) const;
|
||||
virtual void add (Serializer & s) const;
|
||||
|
||||
void sort (bool (*compare) (const STObject & o1, const STObject & o2));
|
||||
|
||||
bool operator== (const STArray & s)
|
||||
{
|
||||
return value == s.value;
|
||||
}
|
||||
bool operator!= (const STArray & s)
|
||||
{
|
||||
return value != s.value;
|
||||
}
|
||||
|
||||
virtual SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_ARRAY;
|
||||
}
|
||||
virtual bool isEquivalent (const SerializedType & t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return value.empty ();
|
||||
}
|
||||
|
||||
private:
|
||||
vector value;
|
||||
|
||||
STArray* duplicate () const
|
||||
{
|
||||
return new STArray (*this);
|
||||
}
|
||||
static STArray* construct (SerializerIterator&, SField::ref);
|
||||
};
|
||||
|
||||
inline STArray::iterator range_begin (STArray& x)
|
||||
{
|
||||
return x.begin ();
|
||||
}
|
||||
inline STArray::iterator range_end (STArray& x)
|
||||
{
|
||||
return x.end ();
|
||||
}
|
||||
|
||||
#endif
|
||||
47
src/ripple_data/protocol/ripple_SerializedObjectTemplate.cpp
Normal file
47
src/ripple_data/protocol/ripple_SerializedObjectTemplate.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
SOTemplate::SOTemplate ()
|
||||
{
|
||||
}
|
||||
|
||||
void SOTemplate::push_back (SOElement const& r)
|
||||
{
|
||||
// Ensure there is the enough space in the index mapping
|
||||
// table for all possible fields.
|
||||
//
|
||||
if (mIndex.empty ())
|
||||
{
|
||||
// Unmapped indices will be set to -1
|
||||
//
|
||||
mIndex.resize (SField::getNumFields () + 1, -1);
|
||||
}
|
||||
|
||||
// Make sure the field's index is in range
|
||||
//
|
||||
assert (r.e_field.getNum () < mIndex.size ());
|
||||
|
||||
// Make sure that this field hasn't already been assigned
|
||||
//
|
||||
assert (getIndex (r.e_field) == -1);
|
||||
|
||||
// Add the field to the index mapping table
|
||||
//
|
||||
mIndex [r.e_field.getNum ()] = mTypes.size ();
|
||||
|
||||
// Append the new element.
|
||||
//
|
||||
mTypes.push_back (new SOElement (r));
|
||||
}
|
||||
|
||||
int SOTemplate::getIndex (SField::ref f) const
|
||||
{
|
||||
// The mapping table should be large enough for any possible field
|
||||
//
|
||||
assert (f.getNum () < mIndex.size ());
|
||||
|
||||
return mIndex[f.getNum ()];
|
||||
}
|
||||
81
src/ripple_data/protocol/ripple_SerializedObjectTemplate.h
Normal file
81
src/ripple_data/protocol/ripple_SerializedObjectTemplate.h
Normal file
@@ -0,0 +1,81 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_SERIALIZEDOBJECTTEMPLATE_H
|
||||
#define RIPPLE_SERIALIZEDOBJECTTEMPLATE_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Flags for elements in a SerializedObjectTemplate.
|
||||
*/
|
||||
// VFALCO NOTE these don't look like bit-flags...
|
||||
enum SOE_Flags
|
||||
{
|
||||
SOE_INVALID = -1,
|
||||
SOE_REQUIRED = 0, // required
|
||||
SOE_OPTIONAL = 1, // optional, may be present with default value
|
||||
SOE_DEFAULT = 2, // optional, if present, must not have default value
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** An element in a SerializedObjectTemplate.
|
||||
*/
|
||||
class SOElement
|
||||
{
|
||||
public:
|
||||
SField::ref const e_field;
|
||||
SOE_Flags const flags;
|
||||
|
||||
SOElement (SField::ref fieldName, SOE_Flags flags)
|
||||
: e_field (fieldName)
|
||||
, flags (flags)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Defines the fields and their attributes within a SerializedObject.
|
||||
|
||||
Each subclass of SerializedObject will provide its own template
|
||||
describing the available fields and their metadata attributes.
|
||||
*/
|
||||
class SOTemplate
|
||||
{
|
||||
public:
|
||||
/** Create an empty template.
|
||||
|
||||
After creating the template, call @ref push_back with the
|
||||
desired fields.
|
||||
|
||||
@see push_back
|
||||
*/
|
||||
SOTemplate ();
|
||||
|
||||
// VFALCO NOTE Why do we even bother with the 'private' keyword if
|
||||
// this function is present?
|
||||
//
|
||||
std::vector <SOElement const*> const& peek () const
|
||||
{
|
||||
return mTypes;
|
||||
}
|
||||
|
||||
/** Add an element to the template.
|
||||
*/
|
||||
void push_back (SOElement const& r);
|
||||
|
||||
/** Retrieve the position of a named field.
|
||||
*/
|
||||
int getIndex (SField::ref) const;
|
||||
|
||||
private:
|
||||
std::vector <SOElement const*> mTypes;
|
||||
|
||||
std::vector <int> mIndex; // field num -> index
|
||||
};
|
||||
|
||||
#endif
|
||||
609
src/ripple_data/protocol/ripple_SerializedTypes.cpp
Normal file
609
src/ripple_data/protocol/ripple_SerializedTypes.cpp
Normal file
@@ -0,0 +1,609 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
SETUP_LOG (SerializedType)
|
||||
|
||||
const STAmount saZero (CURRENCY_ONE, ACCOUNT_ONE, 0);
|
||||
const STAmount saOne (CURRENCY_ONE, ACCOUNT_ONE, 1);
|
||||
|
||||
SerializedType& SerializedType::operator= (const SerializedType& t)
|
||||
{
|
||||
if ((t.fName != fName) && fName->isUseful () && t.fName->isUseful ())
|
||||
{
|
||||
WriteLog ((t.getSType () == STI_AMOUNT) ? lsDEBUG : lsWARNING, SerializedType) // This is common for amounts
|
||||
<< "Caution: " << t.fName->getName () << " not replacing " << fName->getName ();
|
||||
}
|
||||
|
||||
if (!fName->isUseful ()) fName = t.fName;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool SerializedType::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
assert (getSType () == STI_NOTPRESENT);
|
||||
if (t.getSType () == STI_NOTPRESENT)
|
||||
return true;
|
||||
WriteLog (lsDEBUG, SerializedType) << "notEquiv " << getFullText() << " not STI_NOTPRESENT";
|
||||
return false;
|
||||
}
|
||||
|
||||
void STPathSet::printDebug ()
|
||||
{
|
||||
// VFALCO NOTE Can't use Log::out() because of std::endl
|
||||
//
|
||||
for (int i = 0; i < value.size (); i++)
|
||||
{
|
||||
std::cerr << i << ": ";
|
||||
|
||||
for (int j = 0; j < value[i].mPath.size (); j++)
|
||||
{
|
||||
//STPathElement pe = value[i].mPath[j];
|
||||
RippleAddress nad;
|
||||
nad.setAccountID (value[i].mPath[j].mAccountID);
|
||||
std::cerr << " " << nad.humanAccountID ();
|
||||
//std::cerr << " " << pe.mAccountID.GetHex();
|
||||
}
|
||||
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void STPath::printDebug ()
|
||||
{
|
||||
Log::out() << "STPath:";
|
||||
|
||||
for (int i = 0; i < mPath.size (); i++)
|
||||
{
|
||||
RippleAddress nad;
|
||||
nad.setAccountID (mPath[i].mAccountID);
|
||||
Log::out() << " " << i << ": " << nad.humanAccountID ();
|
||||
}
|
||||
}
|
||||
|
||||
std::string SerializedType::getFullText () const
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
if (getSType () != STI_NOTPRESENT)
|
||||
{
|
||||
if (fName->hasName ())
|
||||
{
|
||||
ret = fName->fieldName;
|
||||
ret += " = ";
|
||||
}
|
||||
|
||||
ret += getText ();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
STUInt8* STUInt8::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STUInt8 (name, u.get8 ());
|
||||
}
|
||||
|
||||
std::string STUInt8::getText () const
|
||||
{
|
||||
if (getFName () == sfTransactionResult)
|
||||
{
|
||||
std::string token, human;
|
||||
|
||||
if (transResultInfo (static_cast<TER> (value), token, human))
|
||||
return human;
|
||||
}
|
||||
|
||||
return lexicalCastThrow <std::string> (value);
|
||||
}
|
||||
|
||||
Json::Value STUInt8::getJson (int) const
|
||||
{
|
||||
if (getFName () == sfTransactionResult)
|
||||
{
|
||||
std::string token, human;
|
||||
|
||||
if (transResultInfo (static_cast<TER> (value), token, human))
|
||||
return token;
|
||||
else
|
||||
WriteLog (lsWARNING, SerializedType) << "Unknown result code in metadata: " << value;
|
||||
}
|
||||
|
||||
return 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, SField::ref name)
|
||||
{
|
||||
return new STUInt16 (name, u.get16 ());
|
||||
}
|
||||
|
||||
std::string STUInt16::getText () const
|
||||
{
|
||||
if (getFName () == sfLedgerEntryType)
|
||||
{
|
||||
LedgerFormats::Item const* const item =
|
||||
LedgerFormats::getInstance ()->findByType (static_cast <LedgerEntryType> (value));
|
||||
|
||||
if (item != nullptr)
|
||||
return item->getName ();
|
||||
}
|
||||
|
||||
if (getFName () == sfTransactionType)
|
||||
{
|
||||
TxFormats::Item const* const item =
|
||||
TxFormats::getInstance()->findByType (static_cast <TxType> (value));
|
||||
|
||||
if (item != nullptr)
|
||||
return item->getName ();
|
||||
}
|
||||
|
||||
return lexicalCastThrow <std::string> (value);
|
||||
}
|
||||
|
||||
Json::Value STUInt16::getJson (int) const
|
||||
{
|
||||
if (getFName () == sfLedgerEntryType)
|
||||
{
|
||||
LedgerFormats::Item const* const item =
|
||||
LedgerFormats::getInstance ()->findByType (static_cast <LedgerEntryType> (value));
|
||||
|
||||
if (item != nullptr)
|
||||
return item->getName ();
|
||||
}
|
||||
|
||||
if (getFName () == sfTransactionType)
|
||||
{
|
||||
TxFormats::Item const* const item =
|
||||
TxFormats::getInstance()->findByType (static_cast <TxType> (value));
|
||||
|
||||
if (item != nullptr)
|
||||
return item->getName ();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
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, SField::ref name)
|
||||
{
|
||||
return new STUInt32 (name, u.get32 ());
|
||||
}
|
||||
|
||||
std::string STUInt32::getText () const
|
||||
{
|
||||
return lexicalCastThrow <std::string> (value);
|
||||
}
|
||||
|
||||
Json::Value STUInt32::getJson (int) const
|
||||
{
|
||||
return 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, SField::ref name)
|
||||
{
|
||||
return new STUInt64 (name, u.get64 ());
|
||||
}
|
||||
|
||||
std::string STUInt64::getText () const
|
||||
{
|
||||
return lexicalCastThrow <std::string> (value);
|
||||
}
|
||||
|
||||
Json::Value STUInt64::getJson (int) const
|
||||
{
|
||||
return strHex (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, SField::ref name)
|
||||
{
|
||||
return new STHash128 (name, u.get128 ());
|
||||
}
|
||||
|
||||
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, SField::ref name)
|
||||
{
|
||||
return new STHash160 (name, u.get160 ());
|
||||
}
|
||||
|
||||
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, SField::ref name)
|
||||
{
|
||||
return new STHash256 (name, u.get256 ());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
STVariableLength::STVariableLength (SerializerIterator& st, SField::ref name) : SerializedType (name)
|
||||
{
|
||||
value = st.getVL ();
|
||||
}
|
||||
|
||||
std::string STVariableLength::getText () const
|
||||
{
|
||||
return strHex (value);
|
||||
}
|
||||
|
||||
STVariableLength* STVariableLength::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STVariableLength (name, u.getVL ());
|
||||
}
|
||||
|
||||
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;
|
||||
RippleAddress a;
|
||||
|
||||
if (!getValueH160 (u))
|
||||
return STVariableLength::getText ();
|
||||
|
||||
a.setAccountID (u);
|
||||
return a.humanAccountID ();
|
||||
}
|
||||
|
||||
STAccount* STAccount::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STAccount (name, u.getVL ());
|
||||
}
|
||||
|
||||
//
|
||||
// STVector256
|
||||
//
|
||||
|
||||
// Return a new object from a SerializerIterator.
|
||||
STVector256* STVector256::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
Blob data = u.getVL ();
|
||||
Blob ::iterator begin = data.begin ();
|
||||
|
||||
UPTR_T<STVector256> vec (new STVector256 (name));
|
||||
|
||||
int count = data.size () / (256 / 8);
|
||||
vec->mValue.reserve (count);
|
||||
|
||||
unsigned int uStart = 0;
|
||||
|
||||
for (unsigned int i = 0; i != count; i++)
|
||||
{
|
||||
unsigned int uEnd = uStart + (256 / 8);
|
||||
|
||||
// This next line could be optimized to construct a default uint256 in the vector and then copy into it
|
||||
vec->mValue.push_back (uint256 (Blob (begin + uStart, begin + uEnd)));
|
||||
uStart = uEnd;
|
||||
}
|
||||
|
||||
return vec.release ();
|
||||
}
|
||||
|
||||
void STVector256::add (Serializer& s) const
|
||||
{
|
||||
s.addVL (mValue.empty () ? NULL : mValue[0].begin (), mValue.size () * (256 / 8));
|
||||
}
|
||||
|
||||
bool STVector256::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STVector256* v = dynamic_cast<const STVector256*> (&t);
|
||||
return v && (mValue == v->mValue);
|
||||
}
|
||||
|
||||
bool STVector256::hasValue (uint256 const& v) const
|
||||
{
|
||||
BOOST_FOREACH (uint256 const & hash, mValue)
|
||||
{
|
||||
if (hash == v)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// STAccount
|
||||
//
|
||||
|
||||
STAccount::STAccount (SField::ref n, const uint160& v) : STVariableLength (n)
|
||||
{
|
||||
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
|
||||
}
|
||||
|
||||
bool STAccount::isValueH160 () const
|
||||
{
|
||||
return peekValue ().size () == (160 / 8);
|
||||
}
|
||||
|
||||
void STAccount::setValueH160 (const uint160& v)
|
||||
{
|
||||
peekValue ().clear ();
|
||||
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
|
||||
assert (peekValue ().size () == (160 / 8));
|
||||
}
|
||||
|
||||
bool STAccount::getValueH160 (uint160& v) const
|
||||
{
|
||||
if (!isValueH160 ()) return false;
|
||||
|
||||
memcpy (v.begin (), & (peekValue ().front ()), (160 / 8));
|
||||
return true;
|
||||
}
|
||||
|
||||
RippleAddress STAccount::getValueNCA () const
|
||||
{
|
||||
RippleAddress a;
|
||||
uint160 v;
|
||||
|
||||
if (getValueH160 (v))
|
||||
a.setAccountID (v);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void STAccount::setValueNCA (const RippleAddress& nca)
|
||||
{
|
||||
setValueH160 (nca.getAccountID ());
|
||||
}
|
||||
|
||||
STPathSet* STPathSet::construct (SerializerIterator& s, SField::ref name)
|
||||
{
|
||||
std::vector<STPath> paths;
|
||||
std::vector<STPathElement> path;
|
||||
|
||||
do
|
||||
{
|
||||
int iType = s.get8 ();
|
||||
|
||||
if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary)
|
||||
{
|
||||
if (path.empty ())
|
||||
{
|
||||
WriteLog (lsINFO, SerializedType) << "STPathSet: Empty path.";
|
||||
|
||||
throw std::runtime_error ("empty path");
|
||||
}
|
||||
|
||||
paths.push_back (path);
|
||||
path.clear ();
|
||||
|
||||
if (iType == STPathElement::typeEnd)
|
||||
{
|
||||
return new STPathSet (name, paths);
|
||||
}
|
||||
}
|
||||
else if (iType & ~STPathElement::typeValidBits)
|
||||
{
|
||||
WriteLog (lsINFO, SerializedType) << "STPathSet: Bad path element: " << iType;
|
||||
|
||||
throw std::runtime_error ("bad path element");
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool bAccount = !! (iType & STPathElement::typeAccount);
|
||||
const bool bCurrency = !! (iType & STPathElement::typeCurrency);
|
||||
const bool bIssuer = !! (iType & STPathElement::typeIssuer);
|
||||
|
||||
uint160 uAccountID;
|
||||
uint160 uCurrency;
|
||||
uint160 uIssuerID;
|
||||
|
||||
if (bAccount)
|
||||
uAccountID = s.get160 ();
|
||||
|
||||
if (bCurrency)
|
||||
uCurrency = s.get160 ();
|
||||
|
||||
if (bIssuer)
|
||||
uIssuerID = s.get160 ();
|
||||
|
||||
path.push_back (STPathElement (uAccountID, uCurrency, uIssuerID, bCurrency));
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
bool STPathSet::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STPathSet* v = dynamic_cast<const STPathSet*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
bool STPath::hasSeen (const uint160& uAccountId, const uint160& uCurrencyID, const uint160& uIssuerID) const
|
||||
{
|
||||
for (int i = 0; i < mPath.size (); ++i)
|
||||
{
|
||||
const STPathElement& ele = getElement (i);
|
||||
|
||||
if (ele.getAccountID () == uAccountId
|
||||
&& ele.getCurrency () == uCurrencyID
|
||||
&& ele.getIssuerID () == uIssuerID)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Json::Value STPath::getJson (int) const
|
||||
{
|
||||
Json::Value ret (Json::arrayValue);
|
||||
|
||||
BOOST_FOREACH (std::vector<STPathElement>::const_iterator::value_type it, mPath)
|
||||
{
|
||||
Json::Value elem (Json::objectValue);
|
||||
int iType = it.getNodeType ();
|
||||
|
||||
elem["type"] = iType;
|
||||
elem["type_hex"] = strHex (iType);
|
||||
|
||||
if (iType & STPathElement::typeAccount)
|
||||
elem["account"] = RippleAddress::createHumanAccountID (it.getAccountID ());
|
||||
|
||||
if (iType & STPathElement::typeCurrency)
|
||||
elem["currency"] = STAmount::createHumanCurrency (it.getCurrency ());
|
||||
|
||||
if (iType & STPathElement::typeIssuer)
|
||||
elem["issuer"] = RippleAddress::createHumanAccountID (it.getIssuerID ());
|
||||
|
||||
ret.append (elem);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Json::Value STPathSet::getJson (int options) const
|
||||
{
|
||||
Json::Value ret (Json::arrayValue);
|
||||
|
||||
BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
|
||||
ret.append (it.getJson (options));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::string STPath::getText () const
|
||||
{
|
||||
std::string ret ("[");
|
||||
bool first = true;
|
||||
|
||||
BOOST_FOREACH (const STPathElement & it, mPath)
|
||||
{
|
||||
if (!first) ret += ", ";
|
||||
|
||||
switch (it.getNodeType ())
|
||||
{
|
||||
case STPathElement::typeAccount:
|
||||
{
|
||||
ret += RippleAddress::createHumanAccountID (it.getNode ());
|
||||
break;
|
||||
}
|
||||
|
||||
case STPathElement::typeOffer:
|
||||
{
|
||||
ret += "Offer(";
|
||||
ret += it.getNode ().GetHex ();
|
||||
ret += ")";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error ("Unknown path element");
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
return ret + "]";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
std::string STPathSet::getText () const
|
||||
{
|
||||
std::string ret ("{");
|
||||
bool firstPath = true;
|
||||
|
||||
BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
|
||||
{
|
||||
if (!firstPath)
|
||||
{
|
||||
ret += ", ";
|
||||
firstPath = false;
|
||||
}
|
||||
|
||||
ret += it.getText ();
|
||||
}
|
||||
return ret + "}";
|
||||
}
|
||||
#endif
|
||||
|
||||
void STPathSet::add (Serializer& s) const
|
||||
{
|
||||
bool bFirst = true;
|
||||
|
||||
BOOST_FOREACH (const STPath & spPath, value)
|
||||
{
|
||||
if (!bFirst)
|
||||
{
|
||||
s.add8 (STPathElement::typeBoundary);
|
||||
}
|
||||
|
||||
BOOST_FOREACH (const STPathElement & speElement, spPath)
|
||||
{
|
||||
int iType = speElement.getNodeType ();
|
||||
|
||||
s.add8 (iType);
|
||||
|
||||
if (iType & STPathElement::typeAccount)
|
||||
s.add160 (speElement.getAccountID ());
|
||||
|
||||
if (iType & STPathElement::typeCurrency)
|
||||
s.add160 (speElement.getCurrency ());
|
||||
|
||||
if (iType & STPathElement::typeIssuer)
|
||||
s.add160 (speElement.getIssuerID ());
|
||||
}
|
||||
|
||||
bFirst = false;
|
||||
}
|
||||
s.add8 (STPathElement::typeEnd);
|
||||
}
|
||||
// vim:ts=4
|
||||
1572
src/ripple_data/protocol/ripple_SerializedTypes.h
Normal file
1572
src/ripple_data/protocol/ripple_SerializedTypes.h
Normal file
File diff suppressed because it is too large
Load Diff
735
src/ripple_data/protocol/ripple_Serializer.cpp
Normal file
735
src/ripple_data/protocol/ripple_Serializer.cpp
Normal file
@@ -0,0 +1,735 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
SETUP_LOG (Serializer)
|
||||
|
||||
int Serializer::addZeros (size_t uBytes)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
|
||||
while (uBytes--)
|
||||
mData.push_back (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::add16 (uint16 i)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.push_back (static_cast<unsigned char> (i >> 8));
|
||||
mData.push_back (static_cast<unsigned char> (i & 0xff));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::add32 (uint32 i)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.push_back (static_cast<unsigned char> (i >> 24));
|
||||
mData.push_back (static_cast<unsigned char> ((i >> 16) & 0xff));
|
||||
mData.push_back (static_cast<unsigned char> ((i >> 8) & 0xff));
|
||||
mData.push_back (static_cast<unsigned char> (i & 0xff));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::add64 (uint64 i)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.push_back (static_cast<unsigned char> (i >> 56));
|
||||
mData.push_back (static_cast<unsigned char> ((i >> 48) & 0xff));
|
||||
mData.push_back (static_cast<unsigned char> ((i >> 40) & 0xff));
|
||||
mData.push_back (static_cast<unsigned char> ((i >> 32) & 0xff));
|
||||
mData.push_back (static_cast<unsigned char> ((i >> 24) & 0xff));
|
||||
mData.push_back (static_cast<unsigned char> ((i >> 16) & 0xff));
|
||||
mData.push_back (static_cast<unsigned char> ((i >> 8) & 0xff));
|
||||
mData.push_back (static_cast<unsigned char> (i & 0xff));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::add128 (const uint128& i)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.insert (mData.end (), i.begin (), i.end ());
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::add160 (const uint160& i)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.insert (mData.end (), i.begin (), i.end ());
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::add256 (uint256 const& i)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.insert (mData.end (), i.begin (), i.end ());
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::addRaw (Blob const& vector)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.insert (mData.end (), vector.begin (), vector.end ());
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::addRaw (const Serializer& s)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.insert (mData.end (), s.begin (), s.end ());
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::addRaw (const void* ptr, int len)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.insert (mData.end (), (const char*) ptr, ((const char*)ptr) + len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Serializer::get16 (uint16& o, int offset) const
|
||||
{
|
||||
if ((offset + 2) > mData.size ()) return false;
|
||||
|
||||
const unsigned char* ptr = &mData[offset];
|
||||
o = *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::get32 (uint32& o, int offset) const
|
||||
{
|
||||
if ((offset + 4) > mData.size ()) return false;
|
||||
|
||||
const unsigned char* ptr = &mData[offset];
|
||||
o = *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::get64 (uint64& o, int offset) const
|
||||
{
|
||||
if ((offset + 8) > mData.size ()) return false;
|
||||
|
||||
const unsigned char* ptr = &mData[offset];
|
||||
o = *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr++;
|
||||
o <<= 8;
|
||||
o |= *ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::get128 (uint128& o, int offset) const
|
||||
{
|
||||
if ((offset + (128 / 8)) > mData.size ()) return false;
|
||||
|
||||
memcpy (o.begin (), & (mData.front ()) + offset, (128 / 8));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::get160 (uint160& o, int offset) const
|
||||
{
|
||||
if ((offset + (160 / 8)) > mData.size ()) return false;
|
||||
|
||||
memcpy (o.begin (), & (mData.front ()) + offset, (160 / 8));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::get256 (uint256& o, int offset) const
|
||||
{
|
||||
if ((offset + (256 / 8)) > mData.size ()) return false;
|
||||
|
||||
memcpy (o.begin (), & (mData.front ()) + offset, (256 / 8));
|
||||
return true;
|
||||
}
|
||||
|
||||
uint256 Serializer::get256 (int offset) const
|
||||
{
|
||||
uint256 ret;
|
||||
|
||||
if ((offset + (256 / 8)) > mData.size ()) return ret;
|
||||
|
||||
memcpy (ret.begin (), & (mData.front ()) + offset, (256 / 8));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::addFieldID (int type, int name)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
assert ((type > 0) && (type < 256) && (name > 0) && (name < 256));
|
||||
|
||||
if (type < 16)
|
||||
{
|
||||
if (name < 16) // common type, common name
|
||||
mData.push_back (static_cast<unsigned char> ((type << 4) | name));
|
||||
else
|
||||
{
|
||||
// common type, uncommon name
|
||||
mData.push_back (static_cast<unsigned char> (type << 4));
|
||||
mData.push_back (static_cast<unsigned char> (name));
|
||||
}
|
||||
}
|
||||
else if (name < 16)
|
||||
{
|
||||
// uncommon type, common name
|
||||
mData.push_back (static_cast<unsigned char> (name));
|
||||
mData.push_back (static_cast<unsigned char> (type));
|
||||
}
|
||||
else
|
||||
{
|
||||
// uncommon type, uncommon name
|
||||
mData.push_back (static_cast<unsigned char> (0));
|
||||
mData.push_back (static_cast<unsigned char> (type));
|
||||
mData.push_back (static_cast<unsigned char> (name));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Serializer::getFieldID (int& type, int& name, int offset) const
|
||||
{
|
||||
if (!get8 (type, offset))
|
||||
{
|
||||
WriteLog (lsWARNING, Serializer) << "gFID: unable to get type";
|
||||
return false;
|
||||
}
|
||||
|
||||
name = type & 15;
|
||||
type >>= 4;
|
||||
|
||||
if (type == 0)
|
||||
{
|
||||
// uncommon type
|
||||
if (!get8 (type, ++offset))
|
||||
return false;
|
||||
|
||||
if ((type == 0) || (type < 16))
|
||||
{
|
||||
WriteLog (lsWARNING, Serializer) << "gFID: uncommon type out of range " << type;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == 0)
|
||||
{
|
||||
// uncommon name
|
||||
if (!get8 (name, ++offset))
|
||||
return false;
|
||||
|
||||
if ((name == 0) || (name < 16))
|
||||
{
|
||||
WriteLog (lsWARNING, Serializer) << "gFID: uncommon name out of range " << name;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Serializer::add8 (unsigned char byte)
|
||||
{
|
||||
int ret = mData.size ();
|
||||
mData.push_back (byte);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Serializer::get8 (int& byte, int offset) const
|
||||
{
|
||||
if (offset >= mData.size ()) return false;
|
||||
|
||||
byte = mData[offset];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Serializer::chop (int bytes)
|
||||
{
|
||||
if (bytes > mData.size ()) return false;
|
||||
|
||||
mData.resize (mData.size () - bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
int Serializer::removeLastByte ()
|
||||
{
|
||||
int size = mData.size () - 1;
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
assert (false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = mData[size];
|
||||
mData.resize (size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Serializer::getRaw (Blob& o, int offset, int length) const
|
||||
{
|
||||
if ((offset + length) > mData.size ()) return false;
|
||||
|
||||
o.assign (mData.begin () + offset, mData.begin () + offset + length);
|
||||
return true;
|
||||
}
|
||||
|
||||
Blob Serializer::getRaw (int offset, int length) const
|
||||
{
|
||||
Blob o;
|
||||
|
||||
if ((offset + length) > mData.size ()) return o;
|
||||
|
||||
o.assign (mData.begin () + offset, mData.begin () + offset + length);
|
||||
return o;
|
||||
}
|
||||
|
||||
uint160 Serializer::getRIPEMD160 (int size) const
|
||||
{
|
||||
uint160 ret;
|
||||
|
||||
if ((size < 0) || (size > mData.size ())) size = mData.size ();
|
||||
|
||||
RIPEMD160 (& (mData.front ()), size, (unsigned char*) &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint256 Serializer::getSHA256 (int size) const
|
||||
{
|
||||
uint256 ret;
|
||||
|
||||
if ((size < 0) || (size > mData.size ())) size = mData.size ();
|
||||
|
||||
SHA256 (& (mData.front ()), size, (unsigned char*) &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint256 Serializer::getSHA512Half (int size) const
|
||||
{
|
||||
return getSHA512Half (mData, size);
|
||||
}
|
||||
|
||||
uint256 Serializer::getSHA512Half (Blob const& data, int size)
|
||||
{
|
||||
uint256 j[2];
|
||||
|
||||
if ((size < 0) || (size > data.size ())) size = data.size ();
|
||||
|
||||
SHA512 (& (data.front ()), size, (unsigned char*) j);
|
||||
return j[0];
|
||||
}
|
||||
|
||||
uint256 Serializer::getSHA512Half (const unsigned char* data, int len)
|
||||
{
|
||||
uint256 j[2];
|
||||
SHA512 (data, len, (unsigned char*) j);
|
||||
return j[0];
|
||||
}
|
||||
|
||||
uint256 Serializer::getSHA512Half (const std::string& strData)
|
||||
{
|
||||
return getSHA512Half (reinterpret_cast<const unsigned char*> (strData.data ()), strData.size ());
|
||||
}
|
||||
|
||||
uint256 Serializer::getPrefixHash (uint32 prefix, const unsigned char* data, int len)
|
||||
{
|
||||
char be_prefix[4];
|
||||
be_prefix[0] = static_cast<unsigned char> (prefix >> 24);
|
||||
be_prefix[1] = static_cast<unsigned char> ((prefix >> 16) & 0xff);
|
||||
be_prefix[2] = static_cast<unsigned char> ((prefix >> 8) & 0xff);
|
||||
be_prefix[3] = static_cast<unsigned char> (prefix & 0xff);
|
||||
|
||||
uint256 j[2];
|
||||
SHA512_CTX ctx;
|
||||
SHA512_Init (&ctx);
|
||||
SHA512_Update (&ctx, &be_prefix[0], 4);
|
||||
SHA512_Update (&ctx, data, len);
|
||||
SHA512_Final (reinterpret_cast<unsigned char*> (&j[0]), &ctx);
|
||||
|
||||
return j[0];
|
||||
}
|
||||
|
||||
bool Serializer::checkSignature (int pubkeyOffset, int signatureOffset) const
|
||||
{
|
||||
Blob pubkey, signature;
|
||||
|
||||
if (!getRaw (pubkey, pubkeyOffset, 65)) return false;
|
||||
|
||||
if (!getRaw (signature, signatureOffset, 72)) return false;
|
||||
|
||||
CKey pubCKey;
|
||||
|
||||
if (!pubCKey.SetPubKey (pubkey)) return false;
|
||||
|
||||
return pubCKey.Verify (getSHA512Half (signatureOffset), signature);
|
||||
}
|
||||
|
||||
bool Serializer::checkSignature (Blob const& signature, CKey& key) const
|
||||
{
|
||||
return key.Verify (getSHA512Half (), signature);
|
||||
}
|
||||
|
||||
bool Serializer::makeSignature (Blob& signature, CKey& key) const
|
||||
{
|
||||
return key.Sign (getSHA512Half (), signature);
|
||||
}
|
||||
|
||||
bool Serializer::addSignature (CKey& key)
|
||||
{
|
||||
Blob signature;
|
||||
|
||||
if (!key.Sign (getSHA512Half (), signature)) return false;
|
||||
|
||||
assert (signature.size () == 72);
|
||||
addRaw (signature);
|
||||
return true;
|
||||
}
|
||||
|
||||
int Serializer::addVL (Blob const& vector)
|
||||
{
|
||||
int ret = addRaw (encodeVL (vector.size ()));
|
||||
addRaw (vector);
|
||||
assert (mData.size () == (ret + vector.size () + encodeLengthLength (vector.size ())));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::addVL (const void* ptr, int len)
|
||||
{
|
||||
int ret = addRaw (encodeVL (len));
|
||||
|
||||
if (len)
|
||||
addRaw (ptr, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Serializer::addVL (const std::string& string)
|
||||
{
|
||||
int ret = addRaw (string.size ());
|
||||
|
||||
if (!string.empty ())
|
||||
addRaw (string.data (), string.size ());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Serializer::getVL (Blob& objectVL, int offset, int& length) const
|
||||
{
|
||||
int b1;
|
||||
|
||||
if (!get8 (b1, offset++)) return false;
|
||||
|
||||
int datLen, lenLen = decodeLengthLength (b1);
|
||||
|
||||
try
|
||||
{
|
||||
if (lenLen == 1)
|
||||
datLen = decodeVLLength (b1);
|
||||
else if (lenLen == 2)
|
||||
{
|
||||
int b2;
|
||||
|
||||
if (!get8 (b2, offset++)) return false;
|
||||
|
||||
datLen = decodeVLLength (b1, b2);
|
||||
}
|
||||
else if (lenLen == 3)
|
||||
{
|
||||
int b2, b3;
|
||||
|
||||
if (!get8 (b2, offset++)) return false;
|
||||
|
||||
if (!get8 (b3, offset++)) return false;
|
||||
|
||||
datLen = decodeVLLength (b1, b2, b3);
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
length = lenLen + datLen;
|
||||
return getRaw (objectVL, offset, datLen);
|
||||
}
|
||||
|
||||
bool Serializer::getVLLength (int& length, int offset) const
|
||||
{
|
||||
int b1;
|
||||
|
||||
if (!get8 (b1, offset++)) return false;
|
||||
|
||||
int lenLen = decodeLengthLength (b1);
|
||||
|
||||
try
|
||||
{
|
||||
if (lenLen == 1)
|
||||
length = decodeVLLength (b1);
|
||||
else if (lenLen == 2)
|
||||
{
|
||||
int b2;
|
||||
|
||||
if (!get8 (b2, offset++)) return false;
|
||||
|
||||
length = decodeVLLength (b1, b2);
|
||||
}
|
||||
else if (lenLen == 3)
|
||||
{
|
||||
int b2, b3;
|
||||
|
||||
if (!get8 (b2, offset++)) return false;
|
||||
|
||||
if (!get8 (b3, offset++)) return false;
|
||||
|
||||
length = decodeVLLength (b1, b2, b3);
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Blob Serializer::encodeVL (int length)
|
||||
{
|
||||
unsigned char lenBytes[4];
|
||||
|
||||
if (length <= 192)
|
||||
{
|
||||
lenBytes[0] = static_cast<unsigned char> (length);
|
||||
return Blob (&lenBytes[0], &lenBytes[1]);
|
||||
}
|
||||
else if (length <= 12480)
|
||||
{
|
||||
length -= 193;
|
||||
lenBytes[0] = 193 + static_cast<unsigned char> (length >> 8);
|
||||
lenBytes[1] = static_cast<unsigned char> (length & 0xff);
|
||||
return Blob (&lenBytes[0], &lenBytes[2]);
|
||||
}
|
||||
else if (length <= 918744)
|
||||
{
|
||||
length -= 12481;
|
||||
lenBytes[0] = 241 + static_cast<unsigned char> (length >> 16);
|
||||
lenBytes[1] = static_cast<unsigned char> ((length >> 8) & 0xff);
|
||||
lenBytes[2] = static_cast<unsigned char> (length & 0xff);
|
||||
return Blob (&lenBytes[0], &lenBytes[3]);
|
||||
}
|
||||
else throw std::overflow_error ("lenlen");
|
||||
}
|
||||
|
||||
int Serializer::encodeLengthLength (int length)
|
||||
{
|
||||
if (length < 0) throw std::overflow_error ("len<0");
|
||||
|
||||
if (length <= 192) return 1;
|
||||
|
||||
if (length <= 12480) return 2;
|
||||
|
||||
if (length <= 918744) return 3;
|
||||
|
||||
throw std::overflow_error ("len>918744");
|
||||
}
|
||||
|
||||
int Serializer::decodeLengthLength (int b1)
|
||||
{
|
||||
if (b1 < 0) throw std::overflow_error ("b1<0");
|
||||
|
||||
if (b1 <= 192) return 1;
|
||||
|
||||
if (b1 <= 240) return 2;
|
||||
|
||||
if (b1 <= 254) return 3;
|
||||
|
||||
throw std::overflow_error ("b1>254");
|
||||
}
|
||||
|
||||
int Serializer::decodeVLLength (int b1)
|
||||
{
|
||||
if (b1 < 0) throw std::overflow_error ("b1<0");
|
||||
|
||||
if (b1 > 254) throw std::overflow_error ("b1>254");
|
||||
|
||||
return b1;
|
||||
}
|
||||
|
||||
int Serializer::decodeVLLength (int b1, int b2)
|
||||
{
|
||||
if (b1 < 193) throw std::overflow_error ("b1<193");
|
||||
|
||||
if (b1 > 240) throw std::overflow_error ("b1>240");
|
||||
|
||||
return 193 + (b1 - 193) * 256 + b2;
|
||||
}
|
||||
|
||||
int Serializer::decodeVLLength (int b1, int b2, int b3)
|
||||
{
|
||||
if (b1 < 241) throw std::overflow_error ("b1<241");
|
||||
|
||||
if (b1 > 254) throw std::overflow_error ("b1>254");
|
||||
|
||||
return 12481 + (b1 - 241) * 65536 + b2 * 256 + b3;
|
||||
}
|
||||
|
||||
void Serializer::TestSerializer ()
|
||||
{
|
||||
Serializer s (64);
|
||||
}
|
||||
|
||||
int SerializerIterator::getBytesLeft ()
|
||||
{
|
||||
return mSerializer.size () - mPos;
|
||||
}
|
||||
|
||||
void SerializerIterator::getFieldID (int& type, int& field)
|
||||
{
|
||||
if (!mSerializer.getFieldID (type, field, mPos))
|
||||
throw std::runtime_error ("invalid serializer getFieldID");
|
||||
|
||||
++mPos;
|
||||
|
||||
if (type >= 16)
|
||||
++mPos;
|
||||
|
||||
if (field >= 16)
|
||||
++mPos;
|
||||
}
|
||||
|
||||
unsigned char SerializerIterator::get8 ()
|
||||
{
|
||||
int val;
|
||||
|
||||
if (!mSerializer.get8 (val, mPos)) throw std::runtime_error ("invalid serializer get8");
|
||||
|
||||
++mPos;
|
||||
return val;
|
||||
}
|
||||
|
||||
uint16 SerializerIterator::get16 ()
|
||||
{
|
||||
uint16 val;
|
||||
|
||||
if (!mSerializer.get16 (val, mPos)) throw std::runtime_error ("invalid serializer get16");
|
||||
|
||||
mPos += 16 / 8;
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32 SerializerIterator::get32 ()
|
||||
{
|
||||
uint32 val;
|
||||
|
||||
if (!mSerializer.get32 (val, mPos)) throw std::runtime_error ("invalid serializer get32");
|
||||
|
||||
mPos += 32 / 8;
|
||||
return val;
|
||||
}
|
||||
|
||||
uint64 SerializerIterator::get64 ()
|
||||
{
|
||||
uint64 val;
|
||||
|
||||
if (!mSerializer.get64 (val, mPos)) throw std::runtime_error ("invalid serializer get64");
|
||||
|
||||
mPos += 64 / 8;
|
||||
return val;
|
||||
}
|
||||
|
||||
uint128 SerializerIterator::get128 ()
|
||||
{
|
||||
uint128 val;
|
||||
|
||||
if (!mSerializer.get128 (val, mPos)) throw std::runtime_error ("invalid serializer get128");
|
||||
|
||||
mPos += 128 / 8;
|
||||
return val;
|
||||
}
|
||||
|
||||
uint160 SerializerIterator::get160 ()
|
||||
{
|
||||
uint160 val;
|
||||
|
||||
if (!mSerializer.get160 (val, mPos)) throw std::runtime_error ("invalid serializer get160");
|
||||
|
||||
mPos += 160 / 8;
|
||||
return val;
|
||||
}
|
||||
|
||||
uint256 SerializerIterator::get256 ()
|
||||
{
|
||||
uint256 val;
|
||||
|
||||
if (!mSerializer.get256 (val, mPos)) throw std::runtime_error ("invalid serializer get256");
|
||||
|
||||
mPos += 256 / 8;
|
||||
return val;
|
||||
}
|
||||
|
||||
Blob SerializerIterator::getVL ()
|
||||
{
|
||||
int length;
|
||||
Blob vl;
|
||||
|
||||
if (!mSerializer.getVL (vl, mPos, length)) throw std::runtime_error ("invalid serializer getVL");
|
||||
|
||||
mPos += length;
|
||||
return vl;
|
||||
}
|
||||
|
||||
Blob SerializerIterator::getRaw (int iLength)
|
||||
{
|
||||
int iPos = mPos;
|
||||
mPos += iLength;
|
||||
|
||||
return mSerializer.getRaw (iPos, iLength);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class SerializerTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
SerializerTests () : UnitTest ("Serializer", "ripple")
|
||||
{
|
||||
}
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
beginTestCase ("hash");
|
||||
|
||||
Serializer s1;
|
||||
s1.add32 (3);
|
||||
s1.add256 (uint256 ());
|
||||
|
||||
Serializer s2;
|
||||
s2.add32 (0x12345600);
|
||||
s2.addRaw (s1.peekData ());
|
||||
|
||||
expect (s1.getPrefixHash (0x12345600) == s2.getSHA512Half ());
|
||||
}
|
||||
};
|
||||
|
||||
static SerializerTests serializerTests;
|
||||
|
||||
|
||||
282
src/ripple_data/protocol/ripple_Serializer.h
Normal file
282
src/ripple_data/protocol/ripple_Serializer.h
Normal file
@@ -0,0 +1,282 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_SERIALIZER_H
|
||||
#define RIPPLE_SERIALIZER_H
|
||||
|
||||
class CKey; // forward declaration
|
||||
|
||||
class Serializer
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<Serializer> pointer;
|
||||
|
||||
protected:
|
||||
Blob mData;
|
||||
|
||||
public:
|
||||
Serializer (int n = 256)
|
||||
{
|
||||
mData.reserve (n);
|
||||
}
|
||||
Serializer (Blob const& data) : mData (data)
|
||||
{
|
||||
;
|
||||
}
|
||||
Serializer (const std::string& data) : mData (data.data (), (data.data ()) + data.size ())
|
||||
{
|
||||
;
|
||||
}
|
||||
Serializer (Blob ::iterator begin, Blob ::iterator end) :
|
||||
mData (begin, end)
|
||||
{
|
||||
;
|
||||
}
|
||||
Serializer (Blob ::const_iterator begin, Blob ::const_iterator end) :
|
||||
mData (begin, end)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
// assemble functions
|
||||
int add8 (unsigned char byte);
|
||||
int add16 (uint16);
|
||||
int add32 (uint32); // ledger indexes, account sequence, timestamps
|
||||
int add64 (uint64); // native currency amounts
|
||||
int add128 (const uint128&); // private key generators
|
||||
int add160 (const uint160&); // account names, hankos
|
||||
int add256 (uint256 const& ); // transaction and ledger hashes
|
||||
int addRaw (Blob const& vector);
|
||||
int addRaw (const void* ptr, int len);
|
||||
int addRaw (const Serializer& s);
|
||||
int addZeros (size_t uBytes);
|
||||
|
||||
int addVL (Blob const& vector);
|
||||
int addVL (const std::string& string);
|
||||
int addVL (const void* ptr, int len);
|
||||
|
||||
// disassemble functions
|
||||
bool get8 (int&, int offset) const;
|
||||
bool get8 (unsigned char&, int offset) const;
|
||||
bool get16 (uint16&, int offset) const;
|
||||
bool get32 (uint32&, int offset) const;
|
||||
bool get64 (uint64&, int offset) const;
|
||||
bool get128 (uint128&, int offset) const;
|
||||
bool get160 (uint160&, int offset) const;
|
||||
bool get256 (uint256&, int offset) const;
|
||||
uint256 get256 (int offset) const;
|
||||
bool getRaw (Blob&, int offset, int length) const;
|
||||
Blob getRaw (int offset, int length) const;
|
||||
|
||||
bool getVL (Blob& objectVL, int offset, int& length) const;
|
||||
bool getVLLength (int& length, int offset) const;
|
||||
|
||||
bool getFieldID (int& type, int& name, int offset) const;
|
||||
int addFieldID (int type, int name);
|
||||
int addFieldID (SerializedTypeID type, int name)
|
||||
{
|
||||
return addFieldID (static_cast<int> (type), name);
|
||||
}
|
||||
|
||||
// normal hash functions
|
||||
uint160 getRIPEMD160 (int size = -1) const;
|
||||
uint256 getSHA256 (int size = -1) const;
|
||||
uint256 getSHA512Half (int size = -1) const;
|
||||
static uint256 getSHA512Half (Blob const& data, int size = -1);
|
||||
static uint256 getSHA512Half (const unsigned char* data, int len);
|
||||
static uint256 getSHA512Half (const std::string& strData);
|
||||
|
||||
// prefix hash functions
|
||||
static uint256 getPrefixHash (uint32 prefix, const unsigned char* data, int len);
|
||||
uint256 getPrefixHash (uint32 prefix) const
|
||||
{
|
||||
return getPrefixHash (prefix, & (mData.front ()), mData.size ());
|
||||
}
|
||||
static uint256 getPrefixHash (uint32 prefix, Blob const& data)
|
||||
{
|
||||
return getPrefixHash (prefix, & (data.front ()), data.size ());
|
||||
}
|
||||
static uint256 getPrefixHash (uint32 prefix, const std::string& strData)
|
||||
{
|
||||
return getPrefixHash (prefix, reinterpret_cast<const unsigned char*> (strData.data ()), strData.size ());
|
||||
}
|
||||
|
||||
// totality functions
|
||||
Blob const& peekData () const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
Blob getData () const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
Blob& modData ()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
int getCapacity () const
|
||||
{
|
||||
return mData.capacity ();
|
||||
}
|
||||
int getDataLength () const
|
||||
{
|
||||
return mData.size ();
|
||||
}
|
||||
const void* getDataPtr () const
|
||||
{
|
||||
return &mData.front ();
|
||||
}
|
||||
void* getDataPtr ()
|
||||
{
|
||||
return &mData.front ();
|
||||
}
|
||||
int getLength () const
|
||||
{
|
||||
return mData.size ();
|
||||
}
|
||||
std::string getString () const
|
||||
{
|
||||
return std::string (static_cast<const char*> (getDataPtr ()), size ());
|
||||
}
|
||||
void secureErase ()
|
||||
{
|
||||
memset (& (mData.front ()), 0, mData.size ());
|
||||
erase ();
|
||||
}
|
||||
void erase ()
|
||||
{
|
||||
mData.clear ();
|
||||
}
|
||||
int removeLastByte ();
|
||||
bool chop (int num);
|
||||
|
||||
// vector-like functions
|
||||
Blob ::iterator begin ()
|
||||
{
|
||||
return mData.begin ();
|
||||
}
|
||||
Blob ::iterator end ()
|
||||
{
|
||||
return mData.end ();
|
||||
}
|
||||
Blob ::const_iterator begin () const
|
||||
{
|
||||
return mData.begin ();
|
||||
}
|
||||
Blob ::const_iterator end () const
|
||||
{
|
||||
return mData.end ();
|
||||
}
|
||||
Blob ::size_type size () const
|
||||
{
|
||||
return mData.size ();
|
||||
}
|
||||
void reserve (size_t n)
|
||||
{
|
||||
mData.reserve (n);
|
||||
}
|
||||
void resize (size_t n)
|
||||
{
|
||||
mData.resize (n);
|
||||
}
|
||||
size_t capacity () const
|
||||
{
|
||||
return mData.capacity ();
|
||||
}
|
||||
|
||||
bool operator== (Blob const& v)
|
||||
{
|
||||
return v == mData;
|
||||
}
|
||||
bool operator!= (Blob const& v)
|
||||
{
|
||||
return v != mData;
|
||||
}
|
||||
bool operator== (const Serializer& v)
|
||||
{
|
||||
return v.mData == mData;
|
||||
}
|
||||
bool operator!= (const Serializer& v)
|
||||
{
|
||||
return v.mData != mData;
|
||||
}
|
||||
|
||||
// signature functions
|
||||
bool checkSignature (int pubkeyOffset, int signatureOffset) const;
|
||||
bool checkSignature (Blob const& signature, CKey& rkey) const;
|
||||
bool makeSignature (Blob& signature, CKey& rkey) const;
|
||||
bool addSignature (CKey& rkey);
|
||||
|
||||
// low-level VL length encode/decode functions
|
||||
static Blob encodeVL (int length);
|
||||
static int lengthVL (int length)
|
||||
{
|
||||
return length + encodeLengthLength (length);
|
||||
}
|
||||
static int encodeLengthLength (int length); // length to encode length
|
||||
static int decodeLengthLength (int b1);
|
||||
static int decodeVLLength (int b1);
|
||||
static int decodeVLLength (int b1, int b2);
|
||||
static int decodeVLLength (int b1, int b2, int b3);
|
||||
|
||||
static void TestSerializer ();
|
||||
};
|
||||
|
||||
class SerializerIterator
|
||||
{
|
||||
protected:
|
||||
const Serializer& mSerializer;
|
||||
int mPos;
|
||||
|
||||
public:
|
||||
|
||||
// Reference is not const because we don't want to bind to a temporary
|
||||
SerializerIterator (Serializer& s) : mSerializer (s), mPos (0)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
const Serializer& operator* (void)
|
||||
{
|
||||
return mSerializer;
|
||||
}
|
||||
void reset (void)
|
||||
{
|
||||
mPos = 0;
|
||||
}
|
||||
void setPos (int p)
|
||||
{
|
||||
mPos = p;
|
||||
}
|
||||
|
||||
int getPos (void)
|
||||
{
|
||||
return mPos;
|
||||
}
|
||||
bool empty ()
|
||||
{
|
||||
return mPos == mSerializer.getLength ();
|
||||
}
|
||||
int getBytesLeft ();
|
||||
|
||||
// get functions throw on error
|
||||
unsigned char get8 ();
|
||||
uint16 get16 ();
|
||||
uint32 get32 ();
|
||||
uint64 get64 ();
|
||||
uint128 get128 ();
|
||||
uint160 get160 ();
|
||||
uint256 get256 ();
|
||||
|
||||
void getFieldID (int& type, int& field);
|
||||
|
||||
Blob getRaw (int iLength);
|
||||
|
||||
Blob getVL ();
|
||||
};
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
136
src/ripple_data/protocol/ripple_TER.cpp
Normal file
136
src/ripple_data/protocol/ripple_TER.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman)
|
||||
{
|
||||
static struct
|
||||
{
|
||||
TER terCode;
|
||||
const char* cpToken;
|
||||
const char* cpHuman;
|
||||
} transResultInfoA[] =
|
||||
{
|
||||
{ tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." },
|
||||
{ tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." },
|
||||
{ tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." },
|
||||
{ tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." },
|
||||
{ tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." },
|
||||
{ tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." },
|
||||
{ tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." },
|
||||
{ tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." },
|
||||
{ tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existant line to default." },
|
||||
{ tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." },
|
||||
{ tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." },
|
||||
{ tecMASTER_DISABLED, "tefMASTER_DISABLED", "Master key is disabled." },
|
||||
{ tecNO_REGULAR_KEY, "tefNO_REGULAR_KEY", "Regular key is not set." },
|
||||
|
||||
{ tecUNFUNDED, "tecUNFUNDED", "One of _ADD, _OFFER, or _SEND. Deprecated." },
|
||||
{ tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." },
|
||||
{ tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." },
|
||||
{ tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." },
|
||||
{ tecOWNERS, "tecOWNERS", "Non-zero owner count." },
|
||||
|
||||
{ tefFAILURE, "tefFAILURE", "Failed to apply." },
|
||||
{ tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." },
|
||||
{ tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." },
|
||||
{ tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." },
|
||||
{ tefBAD_CLAIM_ID, "tefBAD_CLAIM_ID", "Malformed: Bad claim id." },
|
||||
{ tefBAD_GEN_AUTH, "tefBAD_GEN_AUTH", "Not authorized to claim generator." },
|
||||
{ tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." },
|
||||
{ tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." },
|
||||
{ tefCREATED, "tefCREATED", "Can't add an already created account." },
|
||||
{ tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." },
|
||||
{ tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." },
|
||||
{ tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." },
|
||||
{ tefINTERNAL, "tefINTERNAL", "Internal error." },
|
||||
{ tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." },
|
||||
{ tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." },
|
||||
{ tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." },
|
||||
{ tefMASTER_DISABLED, "tefMASTER_DISABLED", "Master key is disabled." },
|
||||
|
||||
{ telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." },
|
||||
{ telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." },
|
||||
{ telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." },
|
||||
{ telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." },
|
||||
{ telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." },
|
||||
{ telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." },
|
||||
{ telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." },
|
||||
|
||||
{ temMALFORMED, "temMALFORMED", "Malformed transaction." },
|
||||
{ temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." },
|
||||
{ temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." },
|
||||
{ temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." },
|
||||
{ temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." },
|
||||
{ temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." },
|
||||
{ temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." },
|
||||
{ temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." },
|
||||
{ temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." },
|
||||
{ temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." },
|
||||
{ temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." },
|
||||
{ temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: Bad publish." },
|
||||
{ temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." },
|
||||
{ temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." },
|
||||
{ temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" },
|
||||
{ temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." },
|
||||
{ temBAD_SEND_XRP_LIMIT, "temBAD_SEND_XRP_LIMIT", "Malformed: Limit quality is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_MAX, "temBAD_SEND_XRP_MAX", "Malformed: Send max is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_NO_DIRECT, "temBAD_SEND_XRP_NO_DIRECT", "Malformed: No Ripple direct is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_PARTIAL, "temBAD_SEND_XRP_PARTIAL", "Malformed: Partial payment is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_PATHS, "temBAD_SEND_XRP_PATHS", "Malformed: Paths are not allowed for XRP to XRP." },
|
||||
{ temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." },
|
||||
{ temDST_NEEDED, "temDST_NEEDED", "Destination not specified." },
|
||||
{ temINVALID, "temINVALID", "The transaction is ill-formed." },
|
||||
{ temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." },
|
||||
{ temREDUNDANT, "temREDUNDANT", "Sends same currency to self." },
|
||||
{ temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." },
|
||||
{ temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." },
|
||||
{ temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." },
|
||||
{ temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." },
|
||||
|
||||
{ terRETRY, "terRETRY", "Retry transaction." },
|
||||
{ terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." },
|
||||
{ terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." },
|
||||
{ terLAST, "terLAST", "Process last." },
|
||||
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." },
|
||||
{ terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." },
|
||||
{ terNO_LINE, "terNO_LINE", "No such line." },
|
||||
{ terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." },
|
||||
{ terOWNERS, "terOWNERS", "Non-zero owner count." },
|
||||
|
||||
{ tesSUCCESS, "tesSUCCESS", "The transaction was applied." },
|
||||
};
|
||||
|
||||
int iIndex = NUMBER (transResultInfoA);
|
||||
|
||||
while (iIndex-- && transResultInfoA[iIndex].terCode != terCode)
|
||||
;
|
||||
|
||||
if (iIndex >= 0)
|
||||
{
|
||||
strToken = transResultInfoA[iIndex].cpToken;
|
||||
strHuman = transResultInfoA[iIndex].cpHuman;
|
||||
}
|
||||
|
||||
return iIndex >= 0;
|
||||
}
|
||||
|
||||
std::string transToken (TER terCode)
|
||||
{
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
|
||||
return transResultInfo (terCode, strToken, strHuman) ? strToken : "-";
|
||||
}
|
||||
|
||||
std::string transHuman (TER terCode)
|
||||
{
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
|
||||
return transResultInfo (terCode, strToken, strHuman) ? strHuman : "-";
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
170
src/ripple_data/protocol/ripple_TER.h
Normal file
170
src/ripple_data/protocol/ripple_TER.h
Normal file
@@ -0,0 +1,170 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TER_H
|
||||
#define RIPPLE_TER_H
|
||||
|
||||
// VFALCO TODO do not use auto-incrementing. Explicitly assign each
|
||||
// constant so there is no possibility of someone coming in
|
||||
// and screwing it up.
|
||||
//
|
||||
// VFALCO TODO consider renaming TER to TxErr or TxResult for clarity.
|
||||
//
|
||||
enum TER // aka TransactionEngineResult
|
||||
{
|
||||
// Note: Range is stable. Exact numbers are currently unstable. Use tokens.
|
||||
|
||||
// -399 .. -300: L Local error (transaction fee inadequate, exceeds local limit)
|
||||
// Only valid during non-consensus processing.
|
||||
// Implications:
|
||||
// - Not forwarded
|
||||
// - No fee check
|
||||
telLOCAL_ERROR = -399,
|
||||
telBAD_DOMAIN, // VFALCO TODO should read "telBAD_DOMAIN = -398," etc...
|
||||
telBAD_PATH_COUNT,
|
||||
telBAD_PUBLIC_KEY,
|
||||
telFAILED_PROCESSING,
|
||||
telINSUF_FEE_P,
|
||||
telNO_DST_PARTIAL,
|
||||
|
||||
// -299 .. -200: M Malformed (bad signature)
|
||||
// Causes:
|
||||
// - Transaction corrupt.
|
||||
// Implications:
|
||||
// - Not applied
|
||||
// - Not forwarded
|
||||
// - Reject
|
||||
// - Can not succeed in any imagined ledger.
|
||||
temMALFORMED = -299,
|
||||
temBAD_AMOUNT,
|
||||
temBAD_AUTH_MASTER,
|
||||
temBAD_CURRENCY,
|
||||
temBAD_FEE,
|
||||
temBAD_EXPIRATION,
|
||||
temBAD_ISSUER,
|
||||
temBAD_LIMIT,
|
||||
temBAD_OFFER,
|
||||
temBAD_PATH,
|
||||
temBAD_PATH_LOOP,
|
||||
temBAD_PUBLISH,
|
||||
temBAD_TRANSFER_RATE,
|
||||
temBAD_SEND_XRP_LIMIT,
|
||||
temBAD_SEND_XRP_MAX,
|
||||
temBAD_SEND_XRP_NO_DIRECT,
|
||||
temBAD_SEND_XRP_PARTIAL,
|
||||
temBAD_SEND_XRP_PATHS,
|
||||
temBAD_SIGNATURE,
|
||||
temBAD_SRC_ACCOUNT,
|
||||
temBAD_SEQUENCE,
|
||||
temDST_IS_SRC,
|
||||
temDST_NEEDED,
|
||||
temINVALID,
|
||||
temINVALID_FLAG,
|
||||
temREDUNDANT,
|
||||
temREDUNDANT_SEND_MAX,
|
||||
temRIPPLE_EMPTY,
|
||||
temUNCERTAIN, // An intermediate result used internally, should never be returned.
|
||||
temUNKNOWN,
|
||||
|
||||
// -199 .. -100: F Failure (sequence number previously used)
|
||||
// Causes:
|
||||
// - Transaction cannot succeed because of ledger state.
|
||||
// - Unexpected ledger state.
|
||||
// - C++ exception.
|
||||
// Implications:
|
||||
// - Not applied
|
||||
// - Not forwarded
|
||||
// - Could succeed in an imagined ledger.
|
||||
tefFAILURE = -199,
|
||||
tefALREADY,
|
||||
tefBAD_ADD_AUTH,
|
||||
tefBAD_AUTH,
|
||||
tefBAD_CLAIM_ID,
|
||||
tefBAD_GEN_AUTH,
|
||||
tefBAD_LEDGER,
|
||||
tefCLAIMED,
|
||||
tefCREATED,
|
||||
tefDST_TAG_NEEDED,
|
||||
tefEXCEPTION,
|
||||
tefGEN_IN_USE,
|
||||
tefINTERNAL,
|
||||
tefNO_AUTH_REQUIRED, // Can't set auth if auth is not required.
|
||||
tefPAST_SEQ,
|
||||
tefWRONG_PRIOR,
|
||||
tefMASTER_DISABLED,
|
||||
|
||||
// -99 .. -1: R Retry (sequence too high, no funds for txn fee, originating account non-existent)
|
||||
// Causes:
|
||||
// - Prior application of another, possibly non-existant, another transaction could allow this transaction to succeed.
|
||||
// Implications:
|
||||
// - Not applied
|
||||
// - Not forwarded
|
||||
// - Might succeed later
|
||||
// - Hold
|
||||
// - Makes hole in sequence which jams transactions.
|
||||
terRETRY = -99,
|
||||
terFUNDS_SPENT, // This is a free transaction, therefore don't burden network.
|
||||
terINSUF_FEE_B, // Can't pay fee, therefore don't burden network.
|
||||
terNO_ACCOUNT, // Can't pay fee, therefore don't burden network.
|
||||
terNO_AUTH, // Not authorized to hold IOUs.
|
||||
terNO_LINE, // Internal flag.
|
||||
terOWNERS, // Can't succeed with non-zero owner count.
|
||||
terPRE_SEQ, // Can't pay fee, no point in forwarding, therefore don't burden network.
|
||||
terLAST, // Process after all other transactions
|
||||
|
||||
// 0: S Success (success)
|
||||
// Causes:
|
||||
// - Success.
|
||||
// Implications:
|
||||
// - Applied
|
||||
// - Forwarded
|
||||
tesSUCCESS = 0,
|
||||
|
||||
// 100 .. 129 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path)
|
||||
// Causes:
|
||||
// - Success, but does not achieve optimal result.
|
||||
// - Invalid transaction or no effect, but claim fee to use the sequence number.
|
||||
// Implications:
|
||||
// - Applied
|
||||
// - Forwarded
|
||||
// Only allowed as a return code of appliedTransaction when !tapRetry. Otherwise, treated as terRETRY.
|
||||
//
|
||||
// DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
|
||||
tecCLAIM = 100,
|
||||
tecPATH_PARTIAL = 101,
|
||||
tecUNFUNDED_ADD = 102,
|
||||
tecUNFUNDED_OFFER = 103,
|
||||
tecUNFUNDED_PAYMENT = 104,
|
||||
tecFAILED_PROCESSING = 105,
|
||||
tecDIR_FULL = 121,
|
||||
tecINSUF_RESERVE_LINE = 122,
|
||||
tecINSUF_RESERVE_OFFER = 123,
|
||||
tecNO_DST = 124,
|
||||
tecNO_DST_INSUF_XRP = 125,
|
||||
tecNO_LINE_INSUF_RESERVE = 126,
|
||||
tecNO_LINE_REDUNDANT = 127,
|
||||
tecPATH_DRY = 128,
|
||||
tecUNFUNDED = 129, // Deprecated, old ambiguous unfunded.
|
||||
tecMASTER_DISABLED = 130,
|
||||
tecNO_REGULAR_KEY = 131,
|
||||
tecOWNERS = 132,
|
||||
};
|
||||
|
||||
// VFALCO TODO change these to normal functions.
|
||||
#define isTelLocal(x) ((x) >= telLOCAL_ERROR && (x) < temMALFORMED)
|
||||
#define isTemMalformed(x) ((x) >= temMALFORMED && (x) < tefFAILURE)
|
||||
#define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY)
|
||||
#define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS)
|
||||
#define isTesSuccess(x) ((x) == tesSUCCESS)
|
||||
#define isTecClaim(x) ((x) >= tecCLAIM)
|
||||
|
||||
// VFALCO TODO group these into a shell class along with the defines above.
|
||||
extern bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman);
|
||||
extern std::string transToken (TER terCode);
|
||||
extern std::string transHuman (TER terCode);
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
63
src/ripple_data/protocol/ripple_TxFlags.h
Normal file
63
src/ripple_data/protocol/ripple_TxFlags.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TXFLAGS_H
|
||||
#define RIPPLE_TXFLAGS_H
|
||||
|
||||
//
|
||||
// Transaction flags.
|
||||
//
|
||||
|
||||
/** Transaction flags.
|
||||
|
||||
These flags modify the behavior of an operation.
|
||||
|
||||
@note Changing these will create a hard fork
|
||||
@ingroup protocol
|
||||
*/
|
||||
class TxFlag
|
||||
{
|
||||
public:
|
||||
static uint32 const requireDestTag = 0x00010000;
|
||||
};
|
||||
// VFALCO TODO Move all flags into this container after some study.
|
||||
|
||||
// AccountSet flags:
|
||||
// VFALCO TODO Javadoc comment every one of these constants
|
||||
//const uint32 TxFlag::requireDestTag = 0x00010000;
|
||||
const uint32 tfOptionalDestTag = 0x00020000;
|
||||
const uint32 tfRequireAuth = 0x00040000;
|
||||
const uint32 tfOptionalAuth = 0x00080000;
|
||||
const uint32 tfDisallowXRP = 0x00100000;
|
||||
const uint32 tfAllowXRP = 0x00200000;
|
||||
const uint32 tfAccountSetMask = ~ (TxFlag::requireDestTag | tfOptionalDestTag
|
||||
| tfRequireAuth | tfOptionalAuth
|
||||
| tfDisallowXRP | tfAllowXRP);
|
||||
|
||||
// AccountSet SetFlag/ClearFlag values
|
||||
const uint32 asfRequireDest = 1;
|
||||
const uint32 asfRequireAuth = 2;
|
||||
const uint32 asfDisallowXRP = 3;
|
||||
const uint32 asfDisableMaster = 4;
|
||||
|
||||
// OfferCreate flags:
|
||||
const uint32 tfPassive = 0x00010000;
|
||||
const uint32 tfImmediateOrCancel = 0x00020000;
|
||||
const uint32 tfFillOrKill = 0x00040000;
|
||||
const uint32 tfSell = 0x00080000;
|
||||
const uint32 tfOfferCreateMask = ~ (tfPassive | tfImmediateOrCancel | tfFillOrKill | tfSell);
|
||||
|
||||
// Payment flags:
|
||||
const uint32 tfNoRippleDirect = 0x00010000;
|
||||
const uint32 tfPartialPayment = 0x00020000;
|
||||
const uint32 tfLimitQuality = 0x00040000;
|
||||
const uint32 tfPaymentMask = ~ (tfPartialPayment | tfLimitQuality | tfNoRippleDirect);
|
||||
|
||||
// TrustSet flags:
|
||||
const uint32 tfSetfAuth = 0x00010000;
|
||||
const uint32 tfTrustSetMask = ~ (tfSetfAuth);
|
||||
|
||||
#endif
|
||||
97
src/ripple_data/protocol/ripple_TxFormats.cpp
Normal file
97
src/ripple_data/protocol/ripple_TxFormats.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TxFormats::TxFormats ()
|
||||
: SharedSingleton <TxFormats> (SingletonLifetime::persistAfterCreation)
|
||||
{
|
||||
add ("AccountSet", ttACCOUNT_SET)
|
||||
<< SOElement (sfEmailHash, SOE_OPTIONAL)
|
||||
<< SOElement (sfWalletLocator, SOE_OPTIONAL)
|
||||
<< SOElement (sfWalletSize, SOE_OPTIONAL)
|
||||
<< SOElement (sfMessageKey, SOE_OPTIONAL)
|
||||
<< SOElement (sfDomain, SOE_OPTIONAL)
|
||||
<< SOElement (sfTransferRate, SOE_OPTIONAL)
|
||||
<< SOElement (sfSetFlag, SOE_OPTIONAL)
|
||||
<< SOElement (sfClearFlag, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("TrustSet", ttTRUST_SET)
|
||||
<< SOElement (sfLimitAmount, SOE_OPTIONAL)
|
||||
<< SOElement (sfQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement (sfQualityOut, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("OfferCreate", ttOFFER_CREATE)
|
||||
<< SOElement (sfTakerPays, SOE_REQUIRED)
|
||||
<< SOElement (sfTakerGets, SOE_REQUIRED)
|
||||
<< SOElement (sfExpiration, SOE_OPTIONAL)
|
||||
<< SOElement (sfOfferSequence, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("OfferCancel", ttOFFER_CANCEL)
|
||||
<< SOElement (sfOfferSequence, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
add ("SetRegularKey", ttREGULAR_KEY_SET)
|
||||
<< SOElement (sfRegularKey, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("Payment", ttPAYMENT)
|
||||
<< SOElement (sfDestination, SOE_REQUIRED)
|
||||
<< SOElement (sfAmount, SOE_REQUIRED)
|
||||
<< SOElement (sfSendMax, SOE_OPTIONAL)
|
||||
<< SOElement (sfPaths, SOE_DEFAULT)
|
||||
<< SOElement (sfInvoiceID, SOE_OPTIONAL)
|
||||
<< SOElement (sfDestinationTag, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("Contract", ttCONTRACT)
|
||||
<< SOElement (sfExpiration, SOE_REQUIRED)
|
||||
<< SOElement (sfBondAmount, SOE_REQUIRED)
|
||||
<< SOElement (sfStampEscrow, SOE_REQUIRED)
|
||||
<< SOElement (sfRippleEscrow, SOE_REQUIRED)
|
||||
<< SOElement (sfCreateCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfFundCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfRemoveCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfExpireCode, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("RemoveContract", ttCONTRACT_REMOVE)
|
||||
<< SOElement (sfTarget, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
add ("EnableFeature", ttFEATURE)
|
||||
<< SOElement (sfFeature, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
add ("SetFee", ttFEE)
|
||||
<< SOElement (sfBaseFee, SOE_REQUIRED)
|
||||
<< SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
|
||||
<< SOElement (sfReserveBase, SOE_REQUIRED)
|
||||
<< SOElement (sfReserveIncrement, SOE_REQUIRED)
|
||||
;
|
||||
}
|
||||
|
||||
void TxFormats::addCommonFields (Item& item)
|
||||
{
|
||||
item
|
||||
<< SOElement(sfTransactionType, SOE_REQUIRED)
|
||||
<< SOElement(sfFlags, SOE_OPTIONAL)
|
||||
<< SOElement(sfSourceTag, SOE_OPTIONAL)
|
||||
<< SOElement(sfAccount, SOE_REQUIRED)
|
||||
<< SOElement(sfSequence, SOE_REQUIRED)
|
||||
<< SOElement(sfPreviousTxnID, SOE_OPTIONAL)
|
||||
<< SOElement(sfFee, SOE_REQUIRED)
|
||||
<< SOElement(sfOperationLimit, SOE_OPTIONAL)
|
||||
<< SOElement(sfSigningPubKey, SOE_REQUIRED)
|
||||
<< SOElement(sfTxnSignature, SOE_OPTIONAL)
|
||||
;
|
||||
}
|
||||
|
||||
TxFormats* TxFormats::createInstance ()
|
||||
{
|
||||
return new TxFormats;
|
||||
}
|
||||
57
src/ripple_data/protocol/ripple_TxFormats.h
Normal file
57
src/ripple_data/protocol/ripple_TxFormats.h
Normal file
@@ -0,0 +1,57 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TXFORMATS_H_INCLUDED
|
||||
#define RIPPLE_TXFORMATS_H_INCLUDED
|
||||
|
||||
/** Transaction type identifiers.
|
||||
|
||||
These are part of the binary message format.
|
||||
|
||||
@ingroup protocol
|
||||
*/
|
||||
enum TxType
|
||||
{
|
||||
ttINVALID = -1,
|
||||
|
||||
ttPAYMENT = 0,
|
||||
ttCLAIM = 1, // open
|
||||
ttWALLET_ADD = 2,
|
||||
ttACCOUNT_SET = 3,
|
||||
ttPASSWORD_FUND = 4, // open
|
||||
ttREGULAR_KEY_SET = 5,
|
||||
ttNICKNAME_SET = 6, // open
|
||||
ttOFFER_CREATE = 7,
|
||||
ttOFFER_CANCEL = 8,
|
||||
ttCONTRACT = 9,
|
||||
ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel
|
||||
|
||||
ttTRUST_SET = 20,
|
||||
|
||||
ttFEATURE = 100,
|
||||
ttFEE = 101,
|
||||
};
|
||||
|
||||
/** Manages the list of known transaction formats.
|
||||
*/
|
||||
class TxFormats
|
||||
: public KnownFormats <TxType>
|
||||
, public SharedSingleton <TxFormats>
|
||||
{
|
||||
private:
|
||||
/** Create the object.
|
||||
|
||||
This will load the object will all the known transaction formats.
|
||||
*/
|
||||
TxFormats ();
|
||||
|
||||
void addCommonFields (Item& item);
|
||||
|
||||
public:
|
||||
static TxFormats* createInstance ();
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user