//------------------------------------------------------------------------------ /* 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