bool SetOptionsOpFrame::doApply(AbstractLedgerTxn& ltx) { auto header = ltx.loadHeader(); auto sourceAccount = loadSourceAccount(ltx, header); auto& account = sourceAccount.current().data.account(); if (mSetOptions.inflationDest) { AccountID inflationID = *mSetOptions.inflationDest; if (!(inflationID == getSourceID())) { if (!stellar::loadAccountWithoutRecord(ltx, inflationID)) { innerResult().code(SET_OPTIONS_INVALID_INFLATION); return false; } } account.inflationDest.activate() = inflationID; } if (mSetOptions.clearFlags) { if ((*mSetOptions.clearFlags & allAccountAuthFlags) && isImmutableAuth(sourceAccount)) { innerResult().code(SET_OPTIONS_CANT_CHANGE); return false; } account.flags = account.flags & ~*mSetOptions.clearFlags; } if (mSetOptions.setFlags) { if ((*mSetOptions.setFlags & allAccountAuthFlags) && isImmutableAuth(sourceAccount)) { innerResult().code(SET_OPTIONS_CANT_CHANGE); return false; } account.flags = account.flags | *mSetOptions.setFlags; } if (mSetOptions.homeDomain) { account.homeDomain = *mSetOptions.homeDomain; } if (mSetOptions.masterWeight) { account.thresholds[THRESHOLD_MASTER_WEIGHT] = *mSetOptions.masterWeight & UINT8_MAX; } if (mSetOptions.lowThreshold) { account.thresholds[THRESHOLD_LOW] = *mSetOptions.lowThreshold & UINT8_MAX; } if (mSetOptions.medThreshold) { account.thresholds[THRESHOLD_MED] = *mSetOptions.medThreshold & UINT8_MAX; } if (mSetOptions.highThreshold) { account.thresholds[THRESHOLD_HIGH] = *mSetOptions.highThreshold & UINT8_MAX; } if (mSetOptions.signer) { auto& signers = account.signers; if (mSetOptions.signer->weight) { // add or change signer bool found = false; for (auto& oldSigner : signers) { if (oldSigner.key == mSetOptions.signer->key) { oldSigner.weight = mSetOptions.signer->weight; found = true; } } if (!found) { if (signers.size() == signers.max_size()) { innerResult().code(SET_OPTIONS_TOO_MANY_SIGNERS); return false; } switch (addNumEntries(header, sourceAccount, 1)) { case AddSubentryResult::SUCCESS: break; case AddSubentryResult::LOW_RESERVE: innerResult().code(SET_OPTIONS_LOW_RESERVE); return false; case AddSubentryResult::TOO_MANY_SUBENTRIES: mResult.code(opTOO_MANY_SUBENTRIES); return false; default: throw std::runtime_error( "Unexpected result from addNumEntries"); } signers.push_back(*mSetOptions.signer); } } else { // delete signer auto it = signers.begin(); while (it != signers.end()) { Signer& oldSigner = *it; if (oldSigner.key == mSetOptions.signer->key) { it = signers.erase(it); addNumEntries(header, sourceAccount, -1); } else { it++; } } } normalizeSigners(sourceAccount); } innerResult().code(SET_OPTIONS_SUCCESS); return true; }
// make sure the deleted Account hasn't issued credit // make sure we aren't holding any credit // make sure the we delete all the offers // make sure the we delete all the trustlines // move the XLM to the new account bool MergeOpFrame::doApply(Application& app, AbstractLedgerState& ls) { auto header = ls.loadHeader(); auto otherAccount = stellar::loadAccount(ls, mOperation.body.destination()); if (!otherAccount) { app.getMetrics() .NewMeter({"op-merge", "failure", "no-account"}, "operation") .Mark(); innerResult().code(ACCOUNT_MERGE_NO_ACCOUNT); return false; } int64_t sourceBalance = 0; if (header.current().ledgerVersion > 4 && header.current().ledgerVersion < 8) { // in versions < 8, merge account could be called with a stale account LedgerKey key(ACCOUNT); key.account().accountID = getSourceID(); auto thisAccount = ls.loadWithoutRecord(key); if (!thisAccount) { app.getMetrics() .NewMeter({"op-merge", "failure", "no-account"}, "operation") .Mark(); innerResult().code(ACCOUNT_MERGE_NO_ACCOUNT); return false; } if (header.current().ledgerVersion > 5) { sourceBalance = thisAccount.current().data.account().balance; } } auto sourceAccountEntry = loadSourceAccount(ls, header); auto const& sourceAccount = sourceAccountEntry.current().data.account(); // Only set sourceBalance here if it wasn't set in the previous block if (header.current().ledgerVersion <= 5 || header.current().ledgerVersion >= 8) { sourceBalance = sourceAccount.balance; } if (isImmutableAuth(sourceAccountEntry)) { app.getMetrics() .NewMeter({"op-merge", "failure", "static-auth"}, "operation") .Mark(); innerResult().code(ACCOUNT_MERGE_IMMUTABLE_SET); return false; } if (sourceAccount.numSubEntries != sourceAccount.signers.size()) { app.getMetrics() .NewMeter({"op-merge", "failure", "has-sub-entries"}, "operation") .Mark(); innerResult().code(ACCOUNT_MERGE_HAS_SUB_ENTRIES); return false; } if (header.current().ledgerVersion >= 10) { SequenceNumber maxSeq = getStartingSequenceNumber(header); // don't allow the account to be merged if recreating it would cause it // to jump backwards if (sourceAccount.seqNum >= maxSeq) { app.getMetrics() .NewMeter({"op-merge", "failure", "too-far"}, "operation") .Mark(); innerResult().code(ACCOUNT_MERGE_SEQNUM_TOO_FAR); return false; } } // "success" path starts if (!addBalance(header, otherAccount, sourceBalance)) { app.getMetrics() .NewMeter({"op-merge", "failure", "dest-full"}, "operation") .Mark(); innerResult().code(ACCOUNT_MERGE_DEST_FULL); return false; } sourceAccountEntry.erase(); app.getMetrics() .NewMeter({"op-merge", "success", "apply"}, "operation") .Mark(); innerResult().code(ACCOUNT_MERGE_SUCCESS); innerResult().sourceAccountBalance() = sourceBalance; return true; }