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(); }
/** Reset the context, discarding any changes made and adjust the fee */ XRPAmount Transactor::reset(XRPAmount fee) { ctx_.discard(); auto const txnAcct = view().peek( keylet::account(ctx_.tx.getAccountID(sfAccount))); auto const balance = txnAcct->getFieldAmount (sfBalance).xrp (); // balance should have already been checked in checkFee / preFlight. assert(balance != beast::zero && (!view().open() || balance >= fee)); // We retry/reject the transaction if the account balance is zero or we're // applying against an open ledger and the balance is less than the fee if (fee > balance) fee = balance; // Since we reset the context, we need to charge the fee and update // the account's sequence number again. txnAcct->setFieldAmount (sfBalance, balance - fee); txnAcct->setFieldU32 (sfSequence, ctx_.tx.getSequence() + 1); view().update (txnAcct); return fee; }
void Transactor::setSeq () { auto const sle = view().peek( keylet::account(account_)); std::uint32_t const t_seq = ctx_.tx.getSequence (); sle->setFieldU32 (sfSequence, t_seq + 1); if (sle->isFieldPresent (sfAccountTxnID)) sle->setFieldH256 (sfAccountTxnID, ctx_.tx.getTransactionID ()); }
SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint32 signTime, const RippleAddress& raPub, bool isFull) : STObject(sValidationFormat, sfValidation), mTrusted(false) { // Does not sign setFieldH256(sfLedgerHash, ledgerHash); setFieldU32(sfSigningTime, signTime); setFieldVL(sfSigningPubKey, raPub.getNodePublic()); mNodeID = raPub.getNodeID(); assert(mNodeID.isNonZero()); if (!isFull) setFlag(sFullFlag); }
bool SerializedLedgerEntry::thread (uint256 const& txID, uint32 ledgerSeq, uint256& prevTxID, uint32& prevLedgerID) { uint256 oldPrevTxID = getFieldH256 (sfPreviousTxnID); WriteLog (lsTRACE, SerializedLedgerLog) << "Thread Tx:" << txID << " prev:" << oldPrevTxID; if (oldPrevTxID == txID) { // this transaction is already threaded assert (getFieldU32 (sfPreviousTxnLgrSeq) == ledgerSeq); return false; } prevTxID = oldPrevTxID; prevLedgerID = getFieldU32 (sfPreviousTxnLgrSeq); setFieldH256 (sfPreviousTxnID, txID); setFieldU32 (sfPreviousTxnLgrSeq, ledgerSeq); return true; }
STValidation::STValidation ( uint256 const& ledgerHash, NetClock::time_point signTime, PublicKey const& publicKey, bool isFull) : STObject (getFormat (), sfValidation) , mSeen (signTime) { // Does not sign setFieldH256 (sfLedgerHash, ledgerHash); setFieldU32 (sfSigningTime, signTime.time_since_epoch().count()); setFieldVL (sfSigningPubKey, publicKey.slice()); mNodeID = calcNodeID(publicKey); assert (mNodeID.isNonZero ()); if (isFull) setFlag (kFullFlag); }
bool STLedgerEntry::thread (uint256 const& txID, std::uint32_t ledgerSeq, uint256& prevTxID, std::uint32_t& prevLedgerID) { uint256 oldPrevTxID = getFieldH256 (sfPreviousTxnID); JLOG (debugLog().info()) << "Thread Tx:" << txID << " prev:" << oldPrevTxID; if (oldPrevTxID == txID) { // this transaction is already threaded assert (getFieldU32 (sfPreviousTxnLgrSeq) == ledgerSeq); return false; } prevTxID = oldPrevTxID; prevLedgerID = getFieldU32 (sfPreviousTxnLgrSeq); setFieldH256 (sfPreviousTxnID, txID); setFieldU32 (sfPreviousTxnLgrSeq, ledgerSeq); return true; }
// update the skip list with the information from our previous ledger // VFALCO TODO Document this skip list concept void Ledger::updateSkipList () { if (info_.seq == 0) // genesis ledger has no previous ledger return; std::uint32_t prevIndex = info_.seq - 1; // update record of every 256th ledger if ((prevIndex & 0xff) == 0) { auto const k = keylet::skip(prevIndex); auto sle = peek(k); std::vector<uint256> hashes; bool created; if (! sle) { sle = std::make_shared<SLE>(k); created = true; } else { hashes = static_cast<decltype(hashes)>( sle->getFieldV256(sfHashes)); created = false; } assert (hashes.size () <= 256); hashes.push_back (info_.parentHash); sle->setFieldV256 (sfHashes, STVector256 (hashes)); sle->setFieldU32 (sfLastLedgerSequence, prevIndex); if (created) rawInsert(sle); else rawReplace(sle); } // update record of past 256 ledger auto const k = keylet::skip(); auto sle = peek(k); std::vector <uint256> hashes; bool created; if (! sle) { sle = std::make_shared<SLE>(k); created = true; } else { hashes = static_cast<decltype(hashes)>( sle->getFieldV256 (sfHashes)); created = false; } assert (hashes.size () <= 256); if (hashes.size () == 256) hashes.erase (hashes.begin ()); hashes.push_back (info_.parentHash); sle->setFieldV256 (sfHashes, STVector256 (hashes)); sle->setFieldU32 (sfLastLedgerSequence, prevIndex); if (created) rawInsert(sle); else rawReplace(sle); }
TER SetAccount::doApply () { std::uint32_t const uTxFlags = ctx_.tx.getFlags (); auto const sle = view().peek( keylet::account(account_)); std::uint32_t const uFlagsIn = sle->getFieldU32 (sfFlags); std::uint32_t uFlagsOut = uFlagsIn; std::uint32_t const uSetFlag = ctx_.tx.getFieldU32 (sfSetFlag); std::uint32_t const uClearFlag = ctx_.tx.getFieldU32 (sfClearFlag); // 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); bool sigWithMaster = false; { auto const blob = ctx_.tx.getSigningPubKey(); if (!blob.empty ()) { auto const signingPubKey = RippleAddress::createAccountPublic(blob); if (calcAccountID(signingPubKey) == account_) sigWithMaster = true; } } // // RequireAuth // if (bSetRequireAuth && !(uFlagsIn & lsfRequireAuth)) { j_.trace << "Set RequireAuth."; uFlagsOut |= lsfRequireAuth; } if (bClearRequireAuth && (uFlagsIn & lsfRequireAuth)) { j_.trace << "Clear RequireAuth."; uFlagsOut &= ~lsfRequireAuth; } // // RequireDestTag // if (bSetRequireDest && !(uFlagsIn & lsfRequireDestTag)) { j_.trace << "Set lsfRequireDestTag."; uFlagsOut |= lsfRequireDestTag; } if (bClearRequireDest && (uFlagsIn & lsfRequireDestTag)) { j_.trace << "Clear lsfRequireDestTag."; uFlagsOut &= ~lsfRequireDestTag; } // // DisallowXRP // if (bSetDisallowXRP && !(uFlagsIn & lsfDisallowXRP)) { j_.trace << "Set lsfDisallowXRP."; uFlagsOut |= lsfDisallowXRP; } if (bClearDisallowXRP && (uFlagsIn & lsfDisallowXRP)) { j_.trace << "Clear lsfDisallowXRP."; uFlagsOut &= ~lsfDisallowXRP; } // // DisableMaster // if ((uSetFlag == asfDisableMaster) && !(uFlagsIn & lsfDisableMaster)) { if (!sigWithMaster) { j_.trace << "Must use master key to disable master key."; return tecNEED_MASTER_KEY; } if ((!sle->isFieldPresent (sfRegularKey)) && (!view().peek (keylet::signers (account_)))) { // Account has no regular key or multi-signer signer list. // Prevent transaction changes until we're ready. if (view().rules().enabled(featureMultiSign, ctx_.app.config().features)) return tecNO_ALTERNATIVE_KEY; return tecNO_REGULAR_KEY; } j_.trace << "Set lsfDisableMaster."; uFlagsOut |= lsfDisableMaster; } if ((uClearFlag == asfDisableMaster) && (uFlagsIn & lsfDisableMaster)) { j_.trace << "Clear lsfDisableMaster."; uFlagsOut &= ~lsfDisableMaster; } // // DefaultRipple // if (uSetFlag == asfDefaultRipple) { uFlagsOut |= lsfDefaultRipple; } else if (uClearFlag == asfDefaultRipple) { uFlagsOut &= ~lsfDefaultRipple; } // // NoFreeze // if (uSetFlag == asfNoFreeze) { if (!sigWithMaster && !(uFlagsIn & lsfDisableMaster)) { j_.trace << "Can't use regular key to set NoFreeze."; return tecNEED_MASTER_KEY; } j_.trace << "Set NoFreeze flag"; uFlagsOut |= lsfNoFreeze; } // Anyone may set global freeze if (uSetFlag == asfGlobalFreeze) { j_.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)) { j_.trace << "Clear GlobalFreeze flag"; uFlagsOut &= ~lsfGlobalFreeze; } // // Track transaction IDs signed by this account in its root // if ((uSetFlag == asfAccountTxnID) && !sle->isFieldPresent (sfAccountTxnID)) { j_.trace << "Set AccountTxnID"; sle->makeFieldPresent (sfAccountTxnID); } if ((uClearFlag == asfAccountTxnID) && sle->isFieldPresent (sfAccountTxnID)) { j_.trace << "Clear AccountTxnID"; sle->makeFieldAbsent (sfAccountTxnID); } // // EmailHash // if (ctx_.tx.isFieldPresent (sfEmailHash)) { uint128 const uHash = ctx_.tx.getFieldH128 (sfEmailHash); if (!uHash) { j_.trace << "unset email hash"; sle->makeFieldAbsent (sfEmailHash); } else { j_.trace << "set email hash"; sle->setFieldH128 (sfEmailHash, uHash); } } // // WalletLocator // if (ctx_.tx.isFieldPresent (sfWalletLocator)) { uint256 const uHash = ctx_.tx.getFieldH256 (sfWalletLocator); if (!uHash) { j_.trace << "unset wallet locator"; sle->makeFieldAbsent (sfWalletLocator); } else { j_.trace << "set wallet locator"; sle->setFieldH256 (sfWalletLocator, uHash); } } // // MessageKey // if (ctx_.tx.isFieldPresent (sfMessageKey)) { Blob const messageKey = ctx_.tx.getFieldVL (sfMessageKey); if (messageKey.empty ()) { j_.debug << "set message key"; sle->makeFieldAbsent (sfMessageKey); } else { j_.debug << "set message key"; sle->setFieldVL (sfMessageKey, messageKey); } } // // Domain // if (ctx_.tx.isFieldPresent (sfDomain)) { Blob const domain = ctx_.tx.getFieldVL (sfDomain); if (domain.empty ()) { j_.trace << "unset domain"; sle->makeFieldAbsent (sfDomain); } else { j_.trace << "set domain"; sle->setFieldVL (sfDomain, domain); } } // // TransferRate // if (ctx_.tx.isFieldPresent (sfTransferRate)) { std::uint32_t uRate = ctx_.tx.getFieldU32 (sfTransferRate); if (uRate == 0 || uRate == QUALITY_ONE) { j_.trace << "unset transfer rate"; sle->makeFieldAbsent (sfTransferRate); } else if (uRate > QUALITY_ONE) { j_.trace << "set transfer rate"; sle->setFieldU32 (sfTransferRate, uRate); } } if (uFlagsIn != uFlagsOut) sle->setFieldU32 (sfFlags, uFlagsOut); return tesSUCCESS; }