diff --git a/newcoin.vcxproj b/newcoin.vcxproj
index 6f7548d105..0f21cebefa 100644
--- a/newcoin.vcxproj
+++ b/newcoin.vcxproj
@@ -124,6 +124,7 @@
+
@@ -216,6 +217,7 @@
+
diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters
index fcf37fc266..f569d1ac42 100644
--- a/newcoin.vcxproj.filters
+++ b/newcoin.vcxproj.filters
@@ -291,6 +291,9 @@
Source Files
+
+ Source Files
+
@@ -542,6 +545,9 @@
Header Files
+
+ Header Files
+
diff --git a/src/Interpreter.cpp b/src/Interpreter.cpp
index 0b370683f9..3c539cf307 100644
--- a/src/Interpreter.cpp
+++ b/src/Interpreter.cpp
@@ -1,4 +1,5 @@
#include "Interpreter.h"
+#include "Operation.h"
#include "Config.h"
/*
@@ -8,220 +9,6 @@ We also need to charge for each op
namespace Script {
-
-//////////////////////////////////////////////////////////////////////////
-/// Operations
-
-int Operation::getFee()
-{
- return(theConfig.FEE_CONTRACT_OPERATION);
-}
-
-// this is just an Int in the code
-class IntOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer data=interpreter->getIntData();
- if(data->isInt32())
- {
- interpreter->pushStack( data );
- return(true);
- }
- return(false);
- }
-};
-
-class FloatOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer data=interpreter->getFloatData();
- if(data->isFloat())
- {
- interpreter->pushStack( data );
- return(true);
- }
- return(false);
- }
-};
-
-class Uint160Op : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer data=interpreter->getUint160Data();
- if(data->isUint160())
- {
- interpreter->pushStack( data );
- return(true);
- }
- return(false);
- }
-};
-
-class AddOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer data1=interpreter->popStack();
- Data::pointer data2=interpreter->popStack();
- if( (data1->isInt32() || data1->isFloat()) &&
- (data2->isInt32() || data2->isFloat()) )
- {
- if(data1->isFloat() || data2->isFloat()) interpreter->pushStack(Data::pointer(new FloatData(data1->getFloat()+data2->getFloat())));
- else interpreter->pushStack(Data::pointer(new IntData(data1->getInt()+data2->getInt())));
- return(true);
- }else
- {
- return(false);
- }
- }
-};
-
-class SubOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer data1=interpreter->popStack();
- Data::pointer data2=interpreter->popStack();
- if( (data1->isInt32() || data1->isFloat()) &&
- (data2->isInt32() || data2->isFloat()) )
- {
- if(data1->isFloat() || data2->isFloat()) interpreter->pushStack(Data::pointer(new FloatData(data1->getFloat()-data2->getFloat())));
- else interpreter->pushStack(Data::pointer(new IntData(data1->getInt()-data2->getInt())));
- return(true);
- }else
- {
- return(false);
- }
- }
-};
-
-
-class StartBlockOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer offset=interpreter->getIntData();
- return(interpreter->startBlock(offset->getInt()));
- }
-};
-
-class EndBlockOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- return(interpreter->endBlock());
- }
-};
-
-class StopOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- interpreter->stop();
- return(true);
- }
-};
-
-class AcceptDataOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer data=interpreter->popStack();
- if(data->isInt32())
- {
- interpreter->pushStack( interpreter->getAcceptData(data->getInt()) );
- return(true);
- }
- return(false);
- }
-};
-
-class JumpIfOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer offset=interpreter->getIntData();
- Data::pointer cond=interpreter->popStack();
- if(cond->isBool() && offset->isInt32())
- {
- if(cond->isTrue())
- {
- return(interpreter->jumpTo(offset->getInt()));
- }
- return(true);
- }
- return(false);
- }
-};
-
-class JumpOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer offset=interpreter->getIntData();
- if(offset->isInt32())
- {
- return(interpreter->jumpTo(offset->getInt()));
- }
- return(false);
- }
-};
-
-class SendXNSOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer sourceID=interpreter->popStack();
- Data::pointer destID=interpreter->popStack();
- Data::pointer amount=interpreter->popStack();
- if(sourceID->isUint160() && destID->isUint160() && amount->isInt32() && interpreter->canSign(sourceID->getUint160()))
- {
- // make sure:
- // source is either, this contract, issuer, or acceptor
-
- // TODO do the send
- //interpreter->pushStack( send result);
-
- return(true);
- }
-
- return(false);
- }
-};
-
-class GetDataOp : public Operation
-{
-public:
- bool work(Interpreter* interpreter)
- {
- Data::pointer index=interpreter->popStack();
- if(index->isInt32())
- {
- interpreter->pushStack( interpreter->getContractData(index->getInt()));
- return(true);
- }
-
- return(false);
- }
-};
-
-//////////////////////////////////////////////////////////////////////////
-
Interpreter::Interpreter()
{
mContract=NULL;
@@ -234,14 +21,55 @@ Interpreter::Interpreter()
mBlockJump=0;
mFunctionTable.resize(NUM_OF_OPS);
-
+ /*
mFunctionTable[INT_OP]=new IntOp();
mFunctionTable[FLOAT_OP]=new FloatOp();
mFunctionTable[UINT160_OP]=new Uint160Op();
+ mFunctionTable[BOOL_OP]=new Uint160Op();
+ mFunctionTable[PATH_OP]=new Uint160Op();
mFunctionTable[ADD_OP]=new AddOp();
mFunctionTable[SUB_OP]=new SubOp();
-
+ mFunctionTable[MUL_OP]=new MulOp();
+ mFunctionTable[DIV_OP]=new DivOp();
+ mFunctionTable[MOD_OP]=new ModOp();
+ mFunctionTable[GTR_OP]=new GtrOp();
+ mFunctionTable[LESS_OP]=new LessOp();
+ mFunctionTable[EQUAL_OP]=new SubOp();
+ mFunctionTable[NOT_EQUAL_OP]=new SubOp();
+ mFunctionTable[AND_OP]=new SubOp();
+ mFunctionTable[OR_OP]=new SubOp();
+ mFunctionTable[NOT_OP]=new SubOp();
+ mFunctionTable[JUMP_OP]=new SubOp();
+ mFunctionTable[JUMPIF_OP]=new SubOp();
+ mFunctionTable[STOP_OP]=new SubOp();
+ mFunctionTable[CANCEL_OP]=new SubOp();
+ mFunctionTable[BLOCK_OP]=new SubOp();
+ mFunctionTable[BLOCK_END_OP]=new SubOp();
+ mFunctionTable[SEND_XNS_OP]=new SendXNSOp();
+ mFunctionTable[SEND_OP]=new SendOp();
+ mFunctionTable[REMOVE_CONTRACT_OP]=new SubOp();
+ mFunctionTable[FEE_OP]=new SubOp();
+ mFunctionTable[CHANGE_CONTRACT_OWNER_OP]=new SubOp();
+ mFunctionTable[STOP_REMOVE_OP]=new SubOp();
+ mFunctionTable[SET_DATA_OP]=new SubOp();
+ mFunctionTable[GET_DATA_OP]=new SubOp();
+ mFunctionTable[GET_NUM_DATA_OP]=new SubOp();
+ mFunctionTable[SET_REGISTER_OP]=new SubOp();
+ mFunctionTable[GET_REGISTER_OP]=new SubOp();
+ mFunctionTable[GET_ISSUER_ID_OP]=new SubOp();
+ mFunctionTable[GET_OWNER_ID_OP]=new SubOp();
+ mFunctionTable[GET_LEDGER_TIME_OP]=new SubOp();
+ mFunctionTable[GET_LEDGER_NUM_OP]=new SubOp();
+ mFunctionTable[GET_RAND_FLOAT_OP]=new SubOp();
+ mFunctionTable[GET_XNS_ESCROWED_OP]=new SubOp();
+ mFunctionTable[GET_RIPPLE_ESCROWED_OP]=new SubOp();
+ mFunctionTable[GET_RIPPLE_ESCROWED_CURRENCY_OP]=new SubOp();
+ mFunctionTable[GET_RIPPLE_ESCROWED_ISSUER]=new GetRippleEscrowedIssuerOp();
+ mFunctionTable[GET_ACCEPT_DATA_OP]=new AcceptDataOp();
+ mFunctionTable[GET_ACCEPTOR_ID_OP]=new GetAcceptorIDOp();
+ mFunctionTable[GET_CONTRACT_ID_OP]=new GetContractIDOp();
+ */
}
Data::pointer Interpreter::popStack()
@@ -361,6 +189,11 @@ Data::pointer Interpreter::getContractData(int index)
return(Data::pointer(new ErrorData()));
}
+bool Interpreter::canSign(uint160& signer)
+{
+ return(true);
+}
+
diff --git a/src/Interpreter.h b/src/Interpreter.h
index 5375c1b690..7a0c1d825a 100644
--- a/src/Interpreter.h
+++ b/src/Interpreter.h
@@ -10,20 +10,9 @@
namespace Script {
-class Interpreter;
-
+class Operation;
// Contracts are non typed have variable data types
-
-class Operation
-{
-public:
- // returns false if there was an error
- virtual bool work(Interpreter* interpreter)=0;
-
- virtual int getFee();
-};
-
class Interpreter
{
std::vector mFunctionTable;
@@ -40,16 +29,24 @@ class Interpreter
bool mBlockSuccess;
public:
- enum { INT_OP,FLOAT_OP,UINT160_OP,BOOL_OP,PATH_OP,
+
+
+ enum { INT_OP=1,FLOAT_OP,UINT160_OP,BOOL_OP,PATH_OP,
ADD_OP,SUB_OP,MUL_OP,DIV_OP,MOD_OP,
GTR_OP,LESS_OP,EQUAL_OP,NOT_EQUAL_OP,
AND_OP,OR_OP,NOT_OP,
- BLOCK_OP, BLOCK_END_OP,
JUMP_OP, JUMPIF_OP,
- STOP_OP,
- SET_DATA_OP,GET_DATA_OP, GET_ISSUER_ID_OP, GET_OWNER_ID_OP, GET_LEDGER_TIME_OP,
- ACCEPT_DATA_OP,
- SEND_XNS_OP, NUM_OF_OPS };
+ STOP_OP, CANCEL_OP,
+
+ BLOCK_OP, BLOCK_END_OP,
+ SEND_XNS_OP,SEND_OP,REMOVE_CONTRACT_OP,FEE_OP,CHANGE_CONTRACT_OWNER_OP,
+ STOP_REMOVE_OP,
+ SET_DATA_OP,GET_DATA_OP, GET_NUM_DATA_OP,
+ SET_REGISTER_OP,GET_REGISTER_OP,
+ GET_ISSUER_ID_OP, GET_OWNER_ID_OP, GET_LEDGER_TIME_OP, GET_LEDGER_NUM_OP, GET_RAND_FLOAT_OP,
+ GET_XNS_ESCROWED_OP, GET_RIPPLE_ESCROWED_OP, GET_RIPPLE_ESCROWED_CURRENCY_OP, GET_RIPPLE_ESCROWED_ISSUER,
+ GET_ACCEPT_DATA_OP, GET_ACCEPTOR_ID_OP, GET_CONTRACT_ID_OP,
+ NUM_OF_OPS };
Interpreter();
@@ -58,7 +55,7 @@ public:
void stop();
- bool canSign(const uint160& signer);
+ bool canSign(uint160& signer);
int getInstructionPointer(){ return(mInstructionPointer); }
void setInstructionPointer(int n){ mInstructionPointer=n;}
diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp
index ebe2b08794..8ecccdcd87 100644
--- a/src/LedgerConsensus.cpp
+++ b/src/LedgerConsensus.cpp
@@ -321,12 +321,19 @@ void LedgerConsensus::handleLCL(const uint256& lclHash)
BOOST_FOREACH(Peer::ref peer, peerList)
mAcquiringLedger->peerHas(peer);
}
+ if (mHaveCorrectLCL && mProposing)
+ {
+ Log(lsINFO) << "Bowing out of consensus";
+ mOurPosition->bowOut();
+ propose();
+ }
mHaveCorrectLCL = false;
mProposing = false;
mValidating = false;
mCloseTimes.clear();
mPeerPositions.clear();
mDisputes.clear();
+ mDeadNodes.clear();
return;
}
@@ -491,7 +498,7 @@ void LedgerConsensus::statePreClose()
}
else
{
- sinceClose = theApp->getOPs().getLastCloseTime();
+ sinceClose = 1000 * (theApp->getOPs().getCloseTimeNC() - theApp->getOPs().getLastCloseTime());
idleInterval = LEDGER_IDLE_INTERVAL;
}
@@ -517,7 +524,7 @@ void LedgerConsensus::stateEstablish()
if (haveConsensus())
Log(lsINFO) << "We have TX consensus but not CT consensus";
}
- if (haveConsensus())
+ else if (haveConsensus())
{
Log(lsINFO) << "Converge cutoff (" << mPeerPositions.size() << " participants)";
mState = lcsFINISHED;
@@ -638,7 +645,7 @@ void LedgerConsensus::updateOurPositions()
for (std::map::iterator it = closeTimes.begin(), end = closeTimes.end(); it != end; ++it)
{
- Log(lsINFO) << "CCTime: " << it->first << " has " << it->second << " out of " << thresh;
+ Log(lsINFO) << "CCTime: " << it->first << " has " << it->second << ", " << thresh << " required";
if (it->second > thresh)
{
Log(lsINFO) << "Close time consensus reached: " << it->first;
@@ -794,11 +801,18 @@ void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vec
bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition)
{
- LedgerProposal::pointer& currentPosition = mPeerPositions[newPosition->getPeerID()];
+ uint160 peerID = newPosition->getPeerID();
+ if (mDeadNodes.find(peerID) != mDeadNodes.end())
+ {
+ Log(lsINFO) << "Position from dead node";
+ return false;
+ }
+
+ LedgerProposal::pointer& currentPosition = mPeerPositions[peerID];
if (currentPosition)
{
- assert(newPosition->getPeerID() == currentPosition->getPeerID());
+ assert(peerID == currentPosition->getPeerID());
if (newPosition->getProposeSeq() <= currentPosition->getProposeSeq())
return false;
}
@@ -808,14 +822,24 @@ bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition)
Log(lsTRACE) << "Peer reports close time as " << newPosition->getCloseTime();
++mCloseTimes[newPosition->getCloseTime()];
}
+ else if (newPosition->getProposeSeq() == LedgerProposal::seqLeave)
+ {
+ BOOST_FOREACH(u256_lct_pair& it, mDisputes)
+ it.second->unVote(peerID);
+ mPeerPositions.erase(peerID);
+ mDeadNodes.insert(peerID);
+ return true;
+ }
+
Log(lsINFO) << "Processing peer proposal " << newPosition->getProposeSeq() << "/" << newPosition->getCurrentHash();
currentPosition = newPosition;
+
SHAMap::pointer set = getTransactionTree(newPosition->getCurrentHash(), true);
if (set)
{
BOOST_FOREACH(u256_lct_pair& it, mDisputes)
- it.second->setVote(newPosition->getPeerID(), set->hasItem(it.first));
+ it.second->setVote(peerID, set->hasItem(it.first));
}
else
Log(lsTRACE) << "Don't have that tx set";
diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h
index 4e1db172dd..17aa02691d 100644
--- a/src/LedgerConsensus.h
+++ b/src/LedgerConsensus.h
@@ -115,6 +115,9 @@ protected:
// deferred proposals (node ID -> proposals from that peer)
boost::unordered_map< uint160, std::list > mDeferredProposals;
+ // nodes that have bowed out of this consensus process
+ boost::unordered_set mDeadNodes;
+
// final accept logic
static void Saccept(boost::shared_ptr This, SHAMap::pointer txSet);
void accept(const SHAMap::pointer& txSet);
diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp
index 811f98106e..ef991c9f62 100644
--- a/src/LedgerFormats.cpp
+++ b/src/LedgerFormats.cpp
@@ -23,6 +23,23 @@ LedgerEntryFormat LedgerFormats[]=
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
},
+ { "Contract", ltCONTRACT, {
+ { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
+ { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 },
+ { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 },
+ { S_FIELD(LastTxnID), STI_HASH256, SOE_REQUIRED, 0 },
+ { S_FIELD(LastTxnSeq), STI_UINT32, SOE_REQUIRED, 0 },
+ { S_FIELD(Issuer), STI_ACCOUNT, SOE_REQUIRED, 0 },
+ { S_FIELD(Owner), STI_ACCOUNT, SOE_REQUIRED, 0 },
+ { S_FIELD(Expiration), STI_UINT32, SOE_REQUIRED, 0 },
+ { S_FIELD(BondAmount), STI_UINT32, SOE_REQUIRED, 0 },
+ { S_FIELD(CreateCode), STI_VL, SOE_REQUIRED, 0 },
+ { S_FIELD(FundCode), STI_VL, SOE_REQUIRED, 0 },
+ { S_FIELD(RemoveCode), STI_VL, SOE_REQUIRED, 0 },
+ { S_FIELD(ExpireCode), STI_VL, SOE_REQUIRED, 0 },
+ { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
+ { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
+ },
{ "DirectoryNode", ltDIR_NODE, {
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
{ S_FIELD(Indexes), STI_VECTOR256, SOE_REQUIRED, 0 },
@@ -75,21 +92,6 @@ LedgerEntryFormat LedgerFormats[]=
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
},
- { "Contract", ltCONTRACT, {
- { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
- { S_FIELD(Issuer), STI_ACCOUNT, SOE_REQUIRED, 0 },
- { S_FIELD(Owner), STI_ACCOUNT, SOE_REQUIRED, 0 },
- { S_FIELD(Expiration), STI_UINT32, SOE_REQUIRED, 0 },
- { S_FIELD(BondAmount), STI_UINT32, SOE_REQUIRED, 0 },
- { S_FIELD(StampEscrow), STI_UINT32, SOE_REQUIRED, 0 },
- { S_FIELD(RippleEscrow), STI_AMOUNT, SOE_REQUIRED, 0 },
- { S_FIELD(CreateCode), STI_VL, SOE_REQUIRED, 0 },
- { S_FIELD(FundCode), STI_VL, SOE_REQUIRED, 0 },
- { S_FIELD(RemoveCode), STI_VL, SOE_REQUIRED, 0 },
- { S_FIELD(ExpireCode), STI_VL, SOE_REQUIRED, 0 },
- { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
- { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
- },
{ NULL, ltINVALID }
};
diff --git a/src/LedgerProposal.cpp b/src/LedgerProposal.cpp
index d96b397434..5840c10372 100644
--- a/src/LedgerProposal.cpp
+++ b/src/LedgerProposal.cpp
@@ -62,6 +62,13 @@ void LedgerProposal::changePosition(const uint256& newPosition, uint32 closeTime
++mProposeSeq;
}
+void LedgerProposal::bowOut()
+{
+ mCurrentHash = uint256();
+ mTime = boost::posix_time::second_clock::universal_time();
+ mProposeSeq = seqLeave;
+}
+
std::vector LedgerProposal::sign(void)
{
std::vector ret;
@@ -78,9 +85,14 @@ Json::Value LedgerProposal::getJson() const
{
Json::Value ret = Json::objectValue;
ret["previous_ledger"] = mPreviousLedger.GetHex();
- ret["transaction_hash"] = mCurrentHash.GetHex();
+
+ if (mProposeSeq != seqLeave)
+ {
+ ret["transaction_hash"] = mCurrentHash.GetHex();
+ ret["propose_seq"] = mProposeSeq;
+ }
+
ret["close_time"] = mCloseTime;
- ret["propose_seq"] = mProposeSeq;
if (mPublicKey.isValid())
ret["peer_id"] = mPublicKey.humanNodePublic();
diff --git a/src/LedgerProposal.h b/src/LedgerProposal.h
index 74d0f7c071..adaa557719 100644
--- a/src/LedgerProposal.h
+++ b/src/LedgerProposal.h
@@ -26,6 +26,7 @@ protected:
boost::posix_time::ptime mTime;
public:
+ static const uint32 seqLeave = 0xffffffff; // leaving the consensus process
typedef boost::shared_ptr pointer;
@@ -63,6 +64,7 @@ public:
bool isStale(boost::posix_time::ptime cutoff) { return mTime <= cutoff; }
void changePosition(const uint256& newPosition, uint32 newCloseTime);
+ void bowOut();
Json::Value getJson() const;
};
diff --git a/src/LedgerTiming.cpp b/src/LedgerTiming.cpp
index b19ee994bd..9ce760fc4d 100644
--- a/src/LedgerTiming.cpp
+++ b/src/LedgerTiming.cpp
@@ -27,7 +27,7 @@ bool ContinuousLedgerTiming::shouldClose(
boost::str(boost::format("CLC::shouldClose range Trans=%s, Prop: %d/%d, Secs: %d (last:%d)")
% (anyTransactions ? "yes" : "no") % previousProposers % proposersClosed
% currentMSeconds % previousMSeconds);
- return true;;
+ return true;
}
if (!anyTransactions)