Files
rippled/modules/ripple_app/contracts/ripple_Interpreter.cpp
2013-07-15 09:37:41 -07:00

215 lines
5.5 KiB
C++

//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
/*
We also need to charge for each op
*/
namespace Script
{
Interpreter::Interpreter ()
{
mContract = NULL;
mCode = NULL;
mInstructionPointer = 0;
mTotalFee = 0;
mInBlock = false;
mBlockSuccess = true;
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_XRP_OP] = new SendXRPOp ();
/*
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_XRP_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 ()
{
if (mStack.size ())
{
Data::pointer item = mStack[mStack.size () - 1];
mStack.pop_back ();
return (item);
}
else
{
return (Data::pointer (new ErrorData ()));
}
}
void Interpreter::pushStack (Data::pointer data)
{
mStack.push_back (data);
}
// offset is where to jump to if the block fails
bool Interpreter::startBlock (int offset)
{
if (mInBlock) return (false); // can't nest blocks
mBlockSuccess = true;
mInBlock = true;
mBlockJump = offset + mInstructionPointer;
return (true);
}
bool Interpreter::endBlock ()
{
if (!mInBlock) return (false);
mInBlock = false;
mBlockJump = 0;
pushStack (Data::pointer (new BoolData (mBlockSuccess)));
return (true);
}
TER Interpreter::interpret (Contract* contract, const SerializedTransaction& txn, Blob& code)
{
mContract = contract;
mCode = &code;
mTotalFee = 0;
mInstructionPointer = 0;
while (mInstructionPointer < code.size ())
{
unsigned int fun = (*mCode)[mInstructionPointer];
mInstructionPointer++;
if (fun >= mFunctionTable.size ())
{
// TODO: log
return (temMALFORMED); // TODO: is this actually what we want to do?
}
mTotalFee += mFunctionTable[ fun ]->getFee (); // FIXME: You can't use fees this way, there's no consensus
if (mTotalFee > txn.getTransactionFee ().getNValue ())
{
// TODO: log
return (telINSUF_FEE_P);
}
else
{
if (!mFunctionTable[ fun ]->work (this))
{
// TODO: log
return (temMALFORMED); // TODO: is this actually what we want to do?
}
}
}
return (tesSUCCESS);
}
Data::pointer Interpreter::getIntData ()
{
int value = 0; // TODO
mInstructionPointer += 4;
return (Data::pointer (new IntData (value)));
}
Data::pointer Interpreter::getFloatData ()
{
float value = 0; // TODO
mInstructionPointer += 4;
return (Data::pointer (new FloatData (value)));
}
Data::pointer Interpreter::getUint160Data ()
{
uint160 value; // TODO
mInstructionPointer += 20;
return (Data::pointer (new Uint160Data (value)));
}
bool Interpreter::jumpTo (int offset)
{
mInstructionPointer += offset;
if ( (mInstructionPointer < 0) || (mInstructionPointer > mCode->size ()) )
{
mInstructionPointer -= offset;
return (false);
}
return (true);
}
void Interpreter::stop ()
{
mInstructionPointer = mCode->size ();
}
Data::pointer Interpreter::getContractData (int index)
{
return (Data::pointer (new ErrorData ()));
}
bool Interpreter::canSign (const uint160& signer)
{
return (true);
}
} // end namespace