Пример #1
0
    ter doapply () override
    {
        std::uint32_t const utxflags = mtxn.getflags ();

        std::uint32_t const uflagsin = mtxnaccount->getfieldu32 (sfflags);
        std::uint32_t uflagsout = uflagsin;

        std::uint32_t const usetflag = mtxn.getfieldu32 (sfsetflag);
        std::uint32_t const uclearflag = mtxn.getfieldu32 (sfclearflag);

        if ((usetflag != 0) && (usetflag == uclearflag))
        {
            m_journal.trace << "malformed transaction: set and clear same flag";
            return teminvalid_flag;
        }

        // legacy accountset flags
        bool bsetrequiredest   = (utxflags & txflag::requiredesttag) || (usetflag == asfrequiredest);
        bool bclearrequiredest = (utxflags & tfoptionaldesttag) || (uclearflag == asfrequiredest);
        bool bsetrequireauth   = (utxflags & tfrequireauth) || (usetflag == asfrequireauth);
        bool bclearrequireauth = (utxflags & tfoptionalauth) || (uclearflag == asfrequireauth);
        bool bsetdisallowxrp   = (utxflags & tfdisallowxrp) || (usetflag == asfdisallowxrp);
        bool bcleardisallowxrp = (utxflags & tfallowxrp) || (uclearflag == asfdisallowxrp);

        if (utxflags & tfaccountsetmask)
        {
            m_journal.trace << "malformed transaction: invalid flags set.";
            return teminvalid_flag;
        }

        //
        // requireauth
        //

        if (bsetrequireauth && bclearrequireauth)
        {
            m_journal.trace << "malformed transaction: contradictory flags set.";
            return teminvalid_flag;
        }

        if (bsetrequireauth && !(uflagsin & lsfrequireauth))
        {
            if (!mengine->view().dirisempty (getownerdirindex (mtxnaccountid)))
            {
                m_journal.trace << "retry: owner directory not empty.";
                return (mparams & tapretry) ? terowners : tecowners;
            }

            m_journal.trace << "set requireauth.";
            uflagsout |= lsfrequireauth;
        }

        if (bclearrequireauth && (uflagsin & lsfrequireauth))
        {
            m_journal.trace << "clear requireauth.";
            uflagsout &= ~lsfrequireauth;
        }

        //
        // requiredesttag
        //

        if (bsetrequiredest && bclearrequiredest)
        {
            m_journal.trace << "malformed transaction: contradictory flags set.";
            return teminvalid_flag;
        }

        if (bsetrequiredest && !(uflagsin & lsfrequiredesttag))
        {
            m_journal.trace << "set lsfrequiredesttag.";
            uflagsout |= lsfrequiredesttag;
        }

        if (bclearrequiredest && (uflagsin & lsfrequiredesttag))
        {
            m_journal.trace << "clear lsfrequiredesttag.";
            uflagsout &= ~lsfrequiredesttag;
        }

        //
        // disallowxrp
        //

        if (bsetdisallowxrp && bcleardisallowxrp)
        {
            m_journal.trace << "malformed transaction: contradictory flags set.";
            return teminvalid_flag;
        }

        if (bsetdisallowxrp && !(uflagsin & lsfdisallowxrp))
        {
            m_journal.trace << "set lsfdisallowxrp.";
            uflagsout |= lsfdisallowxrp;
        }

        if (bcleardisallowxrp && (uflagsin & lsfdisallowxrp))
        {
            m_journal.trace << "clear lsfdisallowxrp.";
            uflagsout &= ~lsfdisallowxrp;
        }

        //
        // disablemaster
        //

        if ((usetflag == asfdisablemaster) && !(uflagsin & lsfdisablemaster))
        {
            if (!mtxnaccount->isfieldpresent (sfregularkey))
                return tecno_regular_key;

            m_journal.trace << "set lsfdisablemaster.";
            uflagsout   |= lsfdisablemaster;
        }

        if ((uclearflag == asfdisablemaster) && (uflagsin & lsfdisablemaster))
        {
            m_journal.trace << "clear lsfdisablemaster.";
            uflagsout   &= ~lsfdisablemaster;
        }

        if (usetflag == asfnofreeze)
        {
            m_journal.trace << "set nofreeze flag";
            uflagsout   |= lsfnofreeze;
        }

        // anyone may set global freeze
        if (usetflag == asfglobalfreeze)
        {
            m_journal.trace << "set globalfreeze flag";
            uflagsout   |= lsfglobalfreeze;
        }

        // if you have set nofreeze, you may not clear globalfreeze
        // this prevents those who have set nofreeze from using
        // globalfreeze strategically.
        if ((usetflag != asfglobalfreeze) && (uclearflag == asfglobalfreeze) &&
            ((uflagsout & lsfnofreeze) == 0))
        {
            m_journal.trace << "clear globalfreeze flag";
            uflagsout   &= ~lsfglobalfreeze;
        }

        //
        // track transaction ids signed by this account in its root
        //

        if ((usetflag == asfaccounttxnid) && !mtxnaccount->isfieldpresent (sfaccounttxnid))
        {
            m_journal.trace << "set accounttxnid";
            mtxnaccount->makefieldpresent (sfaccounttxnid);
         }

        if ((uclearflag == asfaccounttxnid) && mtxnaccount->isfieldpresent (sfaccounttxnid))
        {
            m_journal.trace << "clear accounttxnid";
            mtxnaccount->makefieldabsent (sfaccounttxnid);
        }

        //
        // emailhash
        //

        if (mtxn.isfieldpresent (sfemailhash))
        {
            uint128 const uhash = mtxn.getfieldh128 (sfemailhash);

            if (!uhash)
            {
                m_journal.trace << "unset email hash";
                mtxnaccount->makefieldabsent (sfemailhash);
            }
            else
            {
                m_journal.trace << "set email hash";
                mtxnaccount->setfieldh128 (sfemailhash, uhash);
            }
        }

        //
        // walletlocator
        //

        if (mtxn.isfieldpresent (sfwalletlocator))
        {
            uint256 const uhash = mtxn.getfieldh256 (sfwalletlocator);

            if (!uhash)
            {
                m_journal.trace << "unset wallet locator";
                mtxnaccount->makefieldabsent (sfwalletlocator);
            }
            else
            {
                m_journal.trace << "set wallet locator";
                mtxnaccount->setfieldh256 (sfwalletlocator, uhash);
            }
        }

        //
        // messagekey
        //

        if (mtxn.isfieldpresent (sfmessagekey))
        {
            blob messagekey = mtxn.getfieldvl (sfmessagekey);

            if (messagekey.empty ())
            {
                m_journal.debug << "set message key";
                mtxnaccount->makefieldabsent (sfmessagekey);
            }
            if (messagekey.size () > public_bytes_max)
            {
                m_journal.trace << "message key too long";
                return telbad_public_key;
            }
            else
            {
                m_journal.debug << "set message key";
                mtxnaccount->setfieldvl (sfmessagekey, messagekey);
            }
        }

        //
        // domain
        //

        if (mtxn.isfieldpresent (sfdomain))
        {
            blob const domain = mtxn.getfieldvl (sfdomain);

            if (domain.size () > domain_bytes_max)
            {
                m_journal.trace << "domain too long";
                return telbad_domain;
            }

            if (domain.empty ())
            {
                m_journal.trace << "unset domain";
                mtxnaccount->makefieldabsent (sfdomain);
            }
            else
            {
                m_journal.trace << "set domain";
                mtxnaccount->setfieldvl (sfdomain, domain);
            }
        }

        //
        // transferrate
        //

        if (mtxn.isfieldpresent (sftransferrate))
        {
            std::uint32_t urate = mtxn.getfieldu32 (sftransferrate);

            if (!urate || urate == quality_one)
            {
                m_journal.trace << "unset transfer rate";
                mtxnaccount->makefieldabsent (sftransferrate);
            }
            else if (urate > quality_one)
            {
                m_journal.trace << "set transfer rate";
                mtxnaccount->setfieldu32 (sftransferrate, urate);
            }
            else
            {
                m_journal.trace << "bad transfer rate";
                return tembad_transfer_rate;
            }
        }

        if (uflagsin != uflagsout)
            mtxnaccount->setfieldu32 (sfflags, uflagsout);

        return tessuccess;
    }