Exemplo n.º 1
0
Transaction::pointer Transaction::transactionFromSQL (Database* db, bool bValidate)
{
    Serializer rawTxn;
    std::string status;
    uint32 inLedger;

    int txSize = 2048;
    rawTxn.resize (txSize);

    db->getStr ("Status", status);
    inLedger = db->getInt ("LedgerSeq");
    txSize = db->getBinary ("RawTxn", &*rawTxn.begin (), rawTxn.getLength ());

    if (txSize > rawTxn.getLength ())
    {
        rawTxn.resize (txSize);
        db->getBinary ("RawTxn", &*rawTxn.begin (), rawTxn.getLength ());
    }

    rawTxn.resize (txSize);

    SerializerIterator it (rawTxn);
    SerializedTransaction::pointer txn = boost::make_shared<SerializedTransaction> (boost::ref (it));
    Transaction::pointer tr = boost::make_shared<Transaction> (txn, bValidate);

    TransStatus st (INVALID);

    switch (status[0])
    {
    case TXN_SQL_NEW:
        st = NEW;
        break;

    case TXN_SQL_CONFLICT:
        st = CONFLICTED;
        break;

    case TXN_SQL_HELD:
        st = HELD;
        break;

    case TXN_SQL_VALIDATED:
        st = COMMITTED;
        break;

    case TXN_SQL_INCLUDED:
        st = INCLUDED;
        break;

    case TXN_SQL_UNKNOWN:
        break;

    default:
        assert (false);
    }

    tr->setStatus (st);
    tr->setLedger (inLedger);
    return tr;
}
Exemplo n.º 2
0
SerializedTransaction::pointer TransactionMaster::fetch (SHAMapItem::ref item, SHAMapTreeNode::TNType type,
        bool checkDisk, uint32 uCommitLedger)
{
    SerializedTransaction::pointer  txn;
    Transaction::pointer            iTx = getApp().getMasterTransaction ().fetch (item->getTag (), false);

    if (!iTx)
    {

        if (type == SHAMapTreeNode::tnTRANSACTION_NM)
        {
            SerializerIterator sit (item->peekSerializer ());
            txn = boost::make_shared<SerializedTransaction> (boost::ref (sit));
        }
        else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
        {
            Serializer s;
            int length;
            item->peekSerializer ().getVL (s.modData (), 0, length);
            SerializerIterator sit (s);

            txn = boost::make_shared<SerializedTransaction> (boost::ref (sit));
        }
    }
    else
    {
        if (uCommitLedger)
            iTx->setStatus (COMMITTED, uCommitLedger);

        txn = iTx->getSTransaction ();
    }

    return txn;
}
Exemplo n.º 3
0
STTx::pointer TransactionMaster::fetch (std::shared_ptr<SHAMapItem> const& item,
        SHAMapTreeNode::TNType type,
        bool checkDisk, std::uint32_t uCommitLedger)
{
    STTx::pointer  txn;
    Transaction::pointer            iTx = getApp().getMasterTransaction ().fetch (item->getTag (), false);

    if (!iTx)
    {

        if (type == SHAMapTreeNode::tnTRANSACTION_NM)
        {
            SerialIter sit (item->slice());
            txn = std::make_shared<STTx> (std::ref (sit));
        }
        else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
        {
            Serializer s;
            int length;
            item->peekSerializer().getVL (s.modData (), 0, length);
            SerialIter sit (s.slice());

            txn = std::make_shared<STTx> (std::ref (sit));
        }
    }
    else
    {
        if (uCommitLedger)
            iTx->setStatus (COMMITTED, uCommitLedger);

        txn = iTx->getSTransaction ();
    }

    return txn;
}
Exemplo n.º 4
0
// {
//   ledger_hash : <ledger>,
//   ledger_index : <ledger_index>
// }
//
// XXX In this case, not specify either ledger does not mean ledger current. It
// means any ledger.
Json::Value doTransactionEntry (RPC::Context& context)
{
    Ledger::pointer     lpLedger;
    Json::Value jvResult = RPC::lookupLedger (
        context.params_,
        lpLedger,
        context.netOps_);

    if (!lpLedger)
        return jvResult;

    if (!context.params_.isMember ("tx_hash"))
    {
        jvResult["error"]   = "fieldNotFoundTransaction";
    }
    else if (!context.params_.isMember ("ledger_hash")
             && !context.params_.isMember ("ledger_index"))
    {
        // We don't work on ledger current.

        // XXX We don't support any transaction yet.
        jvResult["error"]   = "notYetImplemented";
    }
    else
    {
        uint256 uTransID;
        // XXX Relying on trusted WSS client. Would be better to have a strict
        // routine, returning success or failure.
        uTransID.SetHex (context.params_["tx_hash"].asString ());

        if (!lpLedger)
        {
            jvResult["error"]   = "ledgerNotFound";
        }
        else
        {
            Transaction::pointer        tpTrans;
            TransactionMetaSet::pointer tmTrans;

            if (!lpLedger->getTransaction (uTransID, tpTrans, tmTrans))
            {
                jvResult["error"]   = "transactionNotFound";
            }
            else
            {
                jvResult["tx_json"]     = tpTrans->getJson (0);
                if (tmTrans)
                    jvResult["metadata"]    = tmTrans->getJson (0);
                // 'accounts'
                // 'engine_...'
                // 'ledger_...'
            }
        }
    }

    return jvResult;
}
Exemplo n.º 5
0
bool TransactionMaster::inLedger (uint256 const& hash, std::uint32_t ledger)
{
    Transaction::pointer txn = mCache.fetch (hash);

    if (!txn)
        return false;

    txn->setStatus (COMMITTED, ledger);
    return true;
}
Exemplo n.º 6
0
void find_transaction_history (){
	uint256 hash;
	char hash_ch[32];
	for (int i = 0; i < 32; ++i)	hash_ch[i] = i;
	hash_ch[0] = 1; hash_ch[1] = 2;
	hash.init (hash_ch);

//	vector <Transaction::pointer> vet;
	Account::pointer acc = Bubi::last_ledger->get_account_entry (hash);

	uint256 tx_hash;
	std::uint32_t	tx_seq;

	tx_seq = acc->get_previous_ledger_seq ();
	tx_hash = acc->get_previous_tx_hash ();


	while ( tx_seq != 0 ){
		Transaction::pointer tx = Bubi::last_ledger->get_transaction_entry (tx_hash);
		std::cout << "------------------------------------" << std::endl;
		std::cout << tx->get_source_address ().to_string () << std::endl;
		std::cout << tx->get_destination_address ().to_string () << std::endl;
		std::cout << tx->get_payment_amount () << std::endl;

		if (hash == tx->get_source_address ()){
			tx_seq = tx->get_source_previous_ledger_seq ();
			tx_hash = tx->get_source_previous_tx_hash ();
		}
		else {
			tx_seq = tx->get_destination_previous_ledger_seq ();
			tx_hash = tx->get_destination_previous_tx_hash ();
		}
	}

}
Exemplo n.º 7
0
// DAVID: would you rather duplicate this code or keep the lock longer?
Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
{
	Serializer rawTxn;
	std::string status;
	uint32 inLedger;

	int txSize = 2048;
	rawTxn.resize(txSize);

	{
		ScopedLock sl(theApp->getTxnDB()->getDBLock());
		Database* db = theApp->getTxnDB()->getDB();

		if (!db->executeSQL(sql, true) || !db->startIterRows())
			return Transaction::pointer();

		db->getStr("Status", status);
		inLedger = db->getInt("LedgerSeq");
		txSize = db->getBinary("RawTxn", &*rawTxn.begin(), rawTxn.getLength());
		if (txSize > rawTxn.getLength())
		{
			rawTxn.resize(txSize);
			db->getBinary("RawTxn", &*rawTxn.begin(), rawTxn.getLength());
		}
		db->endIterRows();
	}
	rawTxn.resize(txSize);

	SerializerIterator it(rawTxn);
	SerializedTransaction::pointer txn = boost::make_shared<SerializedTransaction>(boost::ref(it));
	Transaction::pointer tr = boost::make_shared<Transaction>(txn, true);

	TransStatus st(INVALID);
	switch (status[0])
	{
		case TXN_SQL_NEW:			st = NEW;			break;
		case TXN_SQL_CONFLICT:		st = CONFLICTED;	break;
		case TXN_SQL_HELD:			st = HELD;			break;
		case TXN_SQL_VALIDATED:		st = COMMITTED;		break;
		case TXN_SQL_INCLUDED:		st = INCLUDED;		break;
		case TXN_SQL_UNKNOWN:							break;
		default: assert(false);
	}
	tr->setStatus(st);
	tr->setLedger(inLedger);
	return tr;
}
Exemplo n.º 8
0
bool TransactionMaster::canonicalize (Transaction::pointer* pTransaction)
{
    Transaction::pointer txn (*pTransaction);

    uint256 tid = txn->getID ();

    if (!tid)
        return false;

    // VFALCO NOTE canonicalize can change the value of txn!
    if (mCache.canonicalize (tid, txn))
    {
        *pTransaction = txn;
        return true;
    }

    // VFALCO NOTE I am unsure if this is necessary but better safe than sorry.
    *pTransaction = txn;
    return false;
}
Exemplo n.º 9
0
std::vector <Transaction::pointer>	get_transaction_history (std::string acc_pub){
	uint256 hash = string_address_to_uint256 (acc_pub);
	Account::pointer acc = Bubi::last_ledger->get_account_entry (hash);
	std::vector <Transaction::pointer> res;

	uint256 tx_hash;
	std::uint32_t	tx_seq;

	tx_seq = acc->get_previous_ledger_seq ();
	tx_hash = acc->get_previous_tx_hash ();


	while ( tx_seq != 0 ){
		Transaction::pointer tx = Bubi::last_ledger->get_transaction_entry (tx_hash);
		res.push_back (tx);
/*
		std::cout << "------------------------------------" << std::endl;
		std::cout << tx->get_source_address ().to_string () << std::endl;
		std::cout << tx->get_destination_address ().to_string () << std::endl;
		std::cout << tx->get_payment_amount () << std::endl;
*/
		if (hash == tx->get_source_address ()){
			tx_seq = tx->get_source_previous_ledger_seq ();
			tx_hash = tx->get_source_previous_tx_hash ();
		}
		else {
			tx_seq = tx->get_destination_previous_ledger_seq ();
			tx_hash = tx->get_destination_previous_tx_hash ();
		}
	}
	return res;
}
Exemplo n.º 10
0
bool ConsensusTransSetSF::haveNode (const SHAMapNode& id, uint256 const& nodeHash,
                                    Blob& nodeData)
{
    if (getApp().getTempNodeCache ().retrieve (nodeHash, nodeData))
        return true;

    Transaction::pointer txn = getApp().getMasterTransaction().fetch(nodeHash, false);

    if (txn)
    {
        // this is a transaction, and we have it
        WriteLog (lsDEBUG, TransactionAcquire) << "Node in our acquiring TX set is TXN we have";
        Serializer s;
        s.add32 (HashPrefix::transactionID);
        txn->getSTransaction ()->add (s, true);
        assert (s.getSHA512Half () == nodeHash);
        nodeData = s.peekData ();
        return true;
    }

    return false;
}
Exemplo n.º 11
0
// {
//   transaction: <hex>
// }
Json::Value doTx (RPC::Context& context)
{
    context.lock_.unlock ();

    if (!context.params_.isMember (jss::transaction))
        return rpcError (rpcINVALID_PARAMS);

    bool binary = context.params_.isMember (jss::binary) && context.params_[jss::binary].asBool ();

    std::string strTransaction  = context.params_[jss::transaction].asString ();

    if (Transaction::isHexTxID (strTransaction))
    {
        // transaction by ID
        uint256 txid (strTransaction);

        Transaction::pointer txn = getApp().getMasterTransaction ().fetch (txid, true);

        if (!txn)
            return rpcError (rpcTXN_NOT_FOUND);

#ifdef READY_FOR_NEW_TX_FORMAT
        Json::Value ret;
        ret[jss::transaction] = txn->getJson (0, binary);
#else
        Json::Value ret = txn->getJson (0, binary);
#endif

        if (txn->getLedger () != 0)
        {
            Ledger::pointer lgr = context.netOps_.getLedgerBySeq (txn->getLedger ());

            if (lgr)
            {
                bool okay = false;

                if (binary)
                {
                    std::string meta;

                    if (lgr->getMetaHex (txid, meta))
                    {
                        ret[jss::meta] = meta;
                        okay = true;
                    }
                }
                else
                {
                    TransactionMetaSet::pointer set;

                    if (lgr->getTransactionMeta (txid, set))
                    {
                        okay = true;
                        ret[jss::meta] = set->getJson (0);
                    }
                }

                if (okay)
                    ret[jss::validated] = context.netOps_.isValidated (lgr);
            }
        }

        return ret;
    }

    return rpcError (rpcNOT_IMPL);
}
Exemplo n.º 12
0
// {
//   transaction: <hex>
// }
Json::Value RPCHandler::doTx (Json::Value params, Resource::Charge& loadType, Application::ScopedLockType& masterLockHolder)
{
    masterLockHolder.unlock ();

    if (!params.isMember ("transaction"))
        return rpcError (rpcINVALID_PARAMS);

    bool binary = params.isMember ("binary") && params["binary"].asBool ();

    std::string strTransaction  = params["transaction"].asString ();

    if (Transaction::isHexTxID (strTransaction))
    {
        // transaction by ID
        uint256 txid (strTransaction);

        Transaction::pointer txn = getApp().getMasterTransaction ().fetch (txid, true);

        if (!txn)
            return rpcError (rpcTXN_NOT_FOUND);

#ifdef READY_FOR_NEW_TX_FORMAT
        Json::Value ret;
        ret["transaction"] = txn->getJson (0, binary);
#else
        Json::Value ret = txn->getJson (0, binary);
#endif

        if (txn->getLedger () != 0)
        {
            Ledger::pointer lgr = mNetOps->getLedgerBySeq (txn->getLedger ());

            if (lgr)
            {
                bool okay = false;

                if (binary)
                {
                    std::string meta;

                    if (lgr->getMetaHex (txid, meta))
                    {
                        ret["meta"] = meta;
                        okay = true;
                    }
                }
                else
                {
                    TransactionMetaSet::pointer set;

                    if (lgr->getTransactionMeta (txid, set))
                    {
                        okay = true;
                        ret["meta"] = set->getJson (0);
                    }
                }

                if (okay)
                    ret["validated"] = mNetOps->isValidated (lgr);
            }
        }

        return ret;
    }

    return rpcError (rpcNOT_IMPL);
}
Exemplo n.º 13
0
// VFALCO TODO This function should take a reference to the params, modify it
//             as needed, and then there should be a separate function to
//             submit the transaction.
//
Json::Value
transactionSign (
    Json::Value params,
    bool bSubmit,
    bool bFailHard,
    RPCDetail::LedgerFacade& ledgerFacade,
    Role role)
{
    Json::Value jvResult;

    WriteLog (lsDEBUG, RPCHandler) << "transactionSign: " << params;

    if (! params.isMember ("secret"))
        return RPC::missing_field_error ("secret");

    if (! params.isMember ("tx_json"))
        return RPC::missing_field_error ("tx_json");

    RippleAddress naSeed;

    if (! naSeed.setSeedGeneric (params["secret"].asString ()))
        return RPC::make_error (rpcBAD_SEED,
            RPC::invalid_field_message ("secret"));

    Json::Value& tx_json (params ["tx_json"]);

    if (! tx_json.isObject ())
        return RPC::object_field_error ("tx_json");

    if (! tx_json.isMember ("TransactionType"))
        return RPC::missing_field_error ("tx_json.TransactionType");

    std::string const sType = tx_json ["TransactionType"].asString ();

    if (! tx_json.isMember ("Account"))
        return RPC::make_error (rpcSRC_ACT_MISSING,
            RPC::missing_field_message ("tx_json.Account"));

    RippleAddress raSrcAddressID;

    if (! raSrcAddressID.setAccountID (tx_json["Account"].asString ()))
        return RPC::make_error (rpcSRC_ACT_MALFORMED,
            RPC::invalid_field_message ("tx_json.Account"));

    bool const verify = !(params.isMember ("offline")
                          && params["offline"].asBool ());

    if (!tx_json.isMember ("Sequence") && !verify)
        return RPC::missing_field_error ("tx_json.Sequence");

    // Check for current ledger.
    if (verify && !getConfig ().RUN_STANDALONE &&
        (ledgerFacade.getValidatedLedgerAge () > 120))
        return rpcError (rpcNO_CURRENT);

    // Check for load.
    if (ledgerFacade.isLoadedCluster () && (role != Role::ADMIN))
        return rpcError (rpcTOO_BUSY);

    ledgerFacade.snapshotAccountState (raSrcAddressID);

    if (verify) {
        if (!ledgerFacade.isValidAccount ())
        {
            // If not offline and did not find account, error.
            WriteLog (lsDEBUG, RPCHandler)
                << "transactionSign: Failed to find source account "
                << "in current ledger: "
                << raSrcAddressID.humanAccountID ();

            return rpcError (rpcSRC_ACT_NOT_FOUND);
        }
    }

    autofill_fee (params, ledgerFacade, jvResult, role == Role::ADMIN);
    if (RPC::contains_error (jvResult))
        return jvResult;

    if ("Payment" == sType)
    {
        auto e = signPayment(
            params,
            tx_json,
            raSrcAddressID,
            ledgerFacade,
            role);
        if (contains_error(e))
            return e;
    }

    if (!tx_json.isMember ("Sequence"))
        tx_json["Sequence"] = ledgerFacade.getSeq ();

    if (!tx_json.isMember ("Flags"))
        tx_json["Flags"] = tfFullyCanonicalSig;

    if (verify)
    {
        if (!ledgerFacade.hasAccountRoot ())
            // XXX Ignore transactions for accounts not created.
            return rpcError (rpcSRC_ACT_NOT_FOUND);
    }

    RippleAddress secret = RippleAddress::createSeedGeneric (
        params["secret"].asString ());
    RippleAddress masterGenerator = RippleAddress::createGeneratorPublic (
        secret);
    RippleAddress masterAccountPublic = RippleAddress::createAccountPublic (
        masterGenerator, 0);

    if (verify)
    {
        WriteLog (lsTRACE, RPCHandler) <<
                "verify: " << masterAccountPublic.humanAccountID () <<
                " : " << raSrcAddressID.humanAccountID ();

        auto const secretAccountID = masterAccountPublic.getAccountID();
        if (raSrcAddressID.getAccountID () == secretAccountID)
        {
            if (ledgerFacade.accountMasterDisabled ())
                return rpcError (rpcMASTER_DISABLED);
        }
        else if (!ledgerFacade.accountMatchesRegularKey (secretAccountID))
        {
            return rpcError (rpcBAD_SECRET);
        }
    }

    STParsedJSONObject parsed ("tx_json", tx_json);
    if (!parsed.object.get())
    {
        jvResult ["error"] = parsed.error ["error"];
        jvResult ["error_code"] = parsed.error ["error_code"];
        jvResult ["error_message"] = parsed.error ["error_message"];
        return jvResult;
    }
    std::unique_ptr<STObject> sopTrans = std::move(parsed.object);
    sopTrans->setFieldVL (
        sfSigningPubKey,
        masterAccountPublic.getAccountPublic ());

    STTx::pointer stpTrans;

    try
    {
        stpTrans = std::make_shared<STTx> (*sopTrans);
        //WriteLog(lsINFO, RPCHandler) << "radar: before sign " << stpTrans->getFieldAmount(sfAmount);
    }
    catch (std::exception&)
    {
        return RPC::make_error (rpcINTERNAL,
            "Exception occurred during transaction");
    }

    std::string reason;
    if (!passesLocalChecks (*stpTrans, reason))
        return RPC::make_error (rpcINVALID_PARAMS, reason);

    if (params.isMember ("debug_signing"))
    {
        jvResult["tx_unsigned"] = strHex (
            stpTrans->getSerializer ().peekData ());
        jvResult["tx_signing_hash"] = to_string (stpTrans->getSigningHash ());
    }

    // FIXME: For performance, transactions should not be signed in this code
    // path.
    RippleAddress naAccountPrivate = RippleAddress::createAccountPrivate (
        masterGenerator, secret, 0);

    stpTrans->sign (naAccountPrivate);

    Transaction::pointer tpTrans;

    try
    {
        //WriteLog(lsINFO, RPCHandler) << "radar: after sign " << stpTrans->getFieldAmount(sfAmount);
        tpTrans = std::make_shared<Transaction>(stpTrans, Validate::NO);
        //WriteLog(lsINFO, RPCHandler) << "radar: after copy" << tpTrans->getSTransaction()->getFieldAmount(sfAmount);
    }
    catch (std::exception&)
    {
        return RPC::make_error (rpcINTERNAL,
            "Exception occurred during transaction");
    }

    try
    {
        // FIXME: For performance, should use asynch interface.
        tpTrans = ledgerFacade.submitTransactionSync (tpTrans,
            role == Role::ADMIN, true, bFailHard, bSubmit);

        if (!tpTrans)
        {
            return RPC::make_error (rpcINTERNAL,
                "Unable to sterilize transaction.");
        }
    }
    catch (std::exception&)
    {
        return RPC::make_error (rpcINTERNAL,
            "Exception occurred during transaction submission.");
    }

    try
    {
        jvResult["tx_json"] = tpTrans->getJson (0);
        jvResult["tx_blob"] = strHex (
            tpTrans->getSTransaction ()->getSerializer ().peekData ());

        if (temUNCERTAIN != tpTrans->getResult ())
        {
            std::string sToken;
            std::string sHuman;

            transResultInfo (tpTrans->getResult (), sToken, sHuman);

            jvResult["engine_result"]           = sToken;
            jvResult["engine_result_code"]      = tpTrans->getResult ();
            jvResult["engine_result_message"]   = sHuman;
        }

        return jvResult;
    }
    catch (std::exception&)
    {
        return RPC::make_error (rpcINTERNAL,
            "Exception occurred during JSON handling.");
    }
}
Exemplo n.º 14
0
// VFALCO TODO This function should take a reference to the params, modify it
//             as needed, and then there should be a separate function to
//             submit the transaction
//
Json::Value transactionSign (
    Json::Value params, bool bSubmit, bool bFailHard,
    Application::ScopedLockType& mlh, NetworkOPs& netOps, int role)
{
    Json::Value jvResult;

    WriteLog (lsDEBUG, RPCHandler) << "transactionSign: " << params;

    if (! params.isMember ("secret"))
        return RPC::missing_field_error ("secret");

    if (! params.isMember ("tx_json"))
        return RPC::missing_field_error ("tx_json");

    RippleAddress naSeed;

    if (! naSeed.setSeedGeneric (params["secret"].asString ()))
        return RPC::make_error (rpcBAD_SEED,
            RPC::invalid_field_message ("secret"));

    Json::Value& tx_json (params ["tx_json"]);

    if (! tx_json.isObject ())
        return RPC::object_field_error ("tx_json");

    if (! tx_json.isMember ("TransactionType"))
        return RPC::missing_field_error ("tx_json.TransactionType");

    std::string const sType = tx_json ["TransactionType"].asString ();

    if (! tx_json.isMember ("Account"))
        return RPC::make_error (rpcSRC_ACT_MISSING,
            RPC::missing_field_message ("tx_json.Account"));

    RippleAddress raSrcAddressID;

    if (! raSrcAddressID.setAccountID (tx_json["Account"].asString ()))
        return RPC::make_error (rpcSRC_ACT_MALFORMED,
            RPC::invalid_field_message ("tx_json.Account"));

    bool const verify = !(params.isMember ("offline")
                          && params["offline"].asBool ());

    if (!tx_json.isMember ("Sequence") && !verify)
        return RPC::missing_field_error ("tx_json.Sequence");

    // Check for current ledger
    if (verify && !getConfig ().RUN_STANDALONE &&
        (getApp().getLedgerMaster().getValidatedLedgerAge() > 120))
        return rpcError (rpcNO_CURRENT);

    // Check for load
    if (getApp().getFeeTrack().isLoadedCluster() && (role != Config::ADMIN))
        return rpcError(rpcTOO_BUSY);

    Ledger::pointer lSnapshot = netOps.getCurrentLedger ();
    AccountState::pointer asSrc;
    if (verify) {
        asSrc = netOps.getAccountState (lSnapshot, raSrcAddressID);

        if (!asSrc)
        {
            // If not offline and did not find account, error.
            WriteLog (lsDEBUG, RPCHandler)
                    << "transactionSign: Failed to find source account in current ledger: "
                    << raSrcAddressID.humanAccountID ();

            return rpcError (rpcSRC_ACT_NOT_FOUND);
        }
    }

    autofill_fee (params, lSnapshot, jvResult, role == Config::ADMIN);
    if (RPC::contains_error (jvResult))
        return jvResult;

    if ("Payment" == sType)
    {
        auto e = signPayment(params, tx_json, raSrcAddressID, lSnapshot, role);
        if (contains_error(e))
            return e;
    }


    if ("Genesis" == sType)
    {
        auto e = signGenesis(params, tx_json, raSrcAddressID, lSnapshot, role);
        if (contains_error(e))
           return e;
    }

    if ("Transfer" == sType)
    {
        auto e = signTransfer(params, tx_json, raSrcAddressID, lSnapshot, role);
        if (contains_error(e))
           return e;
    }

    if ("AccountCreate" == sType)
    {
        auto e = signAccountCreate(params, tx_json, raSrcAddressID, lSnapshot, role);
        if (contains_error(e))
           return e;
    }


    if (!tx_json.isMember ("Fee")) {
        auto const& transactionType = tx_json["TransactionType"].asString ();
        if ("AccountSet" == transactionType
            || "OfferCreate" == transactionType
            || "OfferCancel" == transactionType
            || "TrustSet" == transactionType)
        {
            tx_json["Fee"] = (int) getConfig ().FEE_DEFAULT;
        }
    }

    if (!tx_json.isMember ("Sequence"))
        tx_json["Sequence"] = asSrc->getSeq ();

    if (!tx_json.isMember ("Flags"))
        tx_json["Flags"] = tfFullyCanonicalSig;

    if (verify)
    {
        SLE::pointer sleAccountRoot = netOps.getSLEi (lSnapshot,
            Ledger::getAccountRootIndex (raSrcAddressID.getAccountID ()));

        if (!sleAccountRoot)
            // XXX Ignore transactions for accounts not created.
            return rpcError (rpcSRC_ACT_NOT_FOUND);
    }

    RippleAddress   naSecret = RippleAddress::createSeedGeneric (params["secret"].asString ());
  
	RippleAddress masterAccountPublic = RippleAddress::createAccountPublic(naSecret);

    if (verify)
    {
        auto account = masterAccountPublic.getAccountID();
        auto const& sle = asSrc->peekSLE();

        WriteLog (lsWARNING, RPCHandler) <<
                "verify: " << masterAccountPublic.humanAccountID () <<
                " : " << raSrcAddressID.humanAccountID ();
        if (raSrcAddressID.getAccountID () == account)
        {
			if (sle.isFlag(lsfDisableMaster) && "Inflation" != sType)
                return rpcError (rpcMASTER_DISABLED);
        }
        else if (!sle.isFieldPresent(sfRegularKey) ||
                 account != sle.getFieldAccount160 (sfRegularKey))
        {
            return rpcError (rpcBAD_SECRET);
        }
    }

    STParsedJSON parsed ("tx_json", tx_json);
    if (!parsed.object.get())
    {
        jvResult ["error"] = parsed.error ["error"];
        jvResult ["error_code"] = parsed.error ["error_code"];
        jvResult ["error_message"] = parsed.error ["error_message"];
        return jvResult;
    }
    std::unique_ptr<STObject> sopTrans = std::move(parsed.object);
    sopTrans->setFieldVL (sfSigningPubKey, masterAccountPublic.getAccountPublic ());

    SerializedTransaction::pointer stpTrans;

    try
    {
        stpTrans = boost::make_shared<SerializedTransaction> (*sopTrans);
    }
    catch (std::exception&)
    {
        return RPC::make_error (rpcINTERNAL,
            "Exception occurred during transaction");
    }

    std::string reason;
    if (!passesLocalChecks (*stpTrans, reason))
        return RPC::make_error (rpcINVALID_PARAMS, reason);

    if (params.isMember ("debug_signing"))
    {
        jvResult["tx_unsigned"] = strHex (
            stpTrans->getSerializer ().peekData ());
        jvResult["tx_signing_hash"] = to_string (stpTrans->getSigningHash ());
    }

    // FIXME: For performance, transactions should not be signed in this code path.
    RippleAddress naAccountPrivate = RippleAddress::createAccountPrivate (naSecret);

    stpTrans->sign (naAccountPrivate);

    Transaction::pointer tpTrans;

    tpTrans = getApp().getMasterTransaction().fetch(stpTrans->getTransactionID(), false);

    if (tpTrans)
    {
        TER res = tpTrans->getResult();
        if (!(isTelLocal(res) || isTemMalformed(res) || isTefFailure(res)))
        {
            tpTrans = Transaction::pointer();
        }
    }

    if (!tpTrans)
    {
        try
        {
            tpTrans     = boost::make_shared<Transaction> (stpTrans, false);
        }
        catch (std::exception&)
        {
            return RPC::make_error (rpcINTERNAL,
                "Exception occurred during transaction");
        }

        try
        {
            // FIXME: For performance, should use asynch interface
            tpTrans = netOps.submitTransactionSync (tpTrans,
                role == Config::ADMIN, true, bFailHard, bSubmit);

            if (!tpTrans)
            {
                return RPC::make_error (rpcINTERNAL,
                    "Unable to sterilize transaction.");
            }
        }
        catch (std::exception&)
        {
            return RPC::make_error (rpcINTERNAL,
                "Exception occurred during transaction submission.");
        }
    }

    try
    {
        jvResult["tx_json"] = tpTrans->getJson (0);
        jvResult["tx_blob"] = strHex (
            tpTrans->getSTransaction ()->getSerializer ().peekData ());

        if (temUNCERTAIN != tpTrans->getResult ())
        {
            std::string sToken;
            std::string sHuman;

            transResultInfo (tpTrans->getResult (), sToken, sHuman);

            jvResult["engine_result"]           = sToken;
            jvResult["engine_result_code"]      = tpTrans->getResult ();
            jvResult["engine_result_message"]   = sHuman;
        }

        return jvResult;
    }
    catch (std::exception&)
    {
        return RPC::make_error (rpcINTERNAL,
            "Exception occurred during JSON handling.");
    }
}