TER SetSignerList::replaceSignerList () { auto const accountKeylet = keylet::account (account_); auto const ownerDirKeylet = keylet::ownerDir (account_); auto const signerListKeylet = keylet::signers (account_); // This may be either a create or a replace. Preemptively remove any // old signer list. May reduce the reserve, so this is done before // checking the reserve. if (TER const ter = removeSignersFromLedger ( accountKeylet, ownerDirKeylet, signerListKeylet)) return ter; auto const sle = view().peek(accountKeylet); // Compute new reserve. Verify the account has funds to meet the reserve. auto const oldOwnerCount = (*sle)[sfOwnerCount]; std::uint32_t const addedOwnerCount = ownerCountDelta (signers_.size ()); auto const newReserve = view().fees().accountReserve(oldOwnerCount + addedOwnerCount); // We check the reserve against the starting balance because we want to // allow dipping into the reserve to pay fees. This behavior is consistent // with CreateTicket. if (mPriorBalance < newReserve) return tecINSUFFICIENT_RESERVE; // Everything's ducky. Add the ltSIGNER_LIST to the ledger. auto signerList = std::make_shared<SLE>(signerListKeylet); view().insert (signerList); writeSignersToSLE (signerList); auto viewJ = ctx_.app.journal ("View"); // Add the signer list to the account's directory. std::uint64_t hint; TER result = dirAdd(ctx_.view (), hint, ownerDirKeylet.key, signerListKeylet.key, describeOwnerDir (account_), viewJ); JLOG(j_.trace) << "Create signer list for account " << toBase58(account_) << ": " << transHuman (result); if (result != tesSUCCESS) return result; signerList->setFieldU64 (sfOwnerNode, hint); // If we succeeded, the new entry counts against the creator's reserve. adjustOwnerCount(view(), sle, addedOwnerCount, viewJ); return result; }
STValidation::STValidation( uint256 const& ledgerHash, std::uint32_t ledgerSeq, uint256 const& consensusHash, NetClock::time_point signTime, PublicKey const& publicKey, SecretKey const& secretKey, NodeID const& nodeID, bool isFull, FeeSettings const& fees, std::vector<uint256> const& amendments) : STObject(getFormat(), sfValidation), mNodeID(nodeID), mSeen(signTime) { // This is our own public key and it should always be valid. if (!publicKeyType(publicKey)) LogicError("Invalid validation public key"); assert(mNodeID.isNonZero()); setFieldH256(sfLedgerHash, ledgerHash); setFieldH256(sfConsensusHash, consensusHash); setFieldU32(sfSigningTime, signTime.time_since_epoch().count()); setFieldVL(sfSigningPubKey, publicKey.slice()); if (isFull) setFlag(kFullFlag); setFieldU32(sfLedgerSequence, ledgerSeq); if (fees.loadFee) setFieldU32(sfLoadFee, *fees.loadFee); if (fees.baseFee) setFieldU64(sfBaseFee, *fees.baseFee); if (fees.reserveBase) setFieldU32(sfReserveBase, *fees.reserveBase); if (fees.reserveIncrement) setFieldU32(sfReserveIncrement, *fees.reserveIncrement); if (!amendments.empty()) setFieldV256(sfAmendments, STVector256(sfAmendments, amendments)); setFlag(vfFullyCanonicalSig); auto const signingHash = getSigningHash(); setFieldVL( sfSignature, signDigest(getSignerPublic(), secretKey, signingHash)); setTrusted(); }