rippled
Change.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/main/Application.h>
21 #include <ripple/app/misc/AmendmentTable.h>
22 #include <ripple/app/misc/NetworkOPs.h>
23 #include <ripple/app/tx/impl/Change.h>
24 #include <ripple/basics/Log.h>
25 #include <ripple/protocol/Indexes.h>
26 #include <ripple/protocol/TxFlags.h>
27 
28 namespace ripple {
29 
30 NotTEC
32 {
33  auto const ret = preflight0(ctx);
34  if (!isTesSuccess(ret))
35  return ret;
36 
37  auto account = ctx.tx.getAccountID(sfAccount);
38  if (account != beast::zero)
39  {
40  JLOG(ctx.j.warn()) << "Change: Bad source id";
41  return temBAD_SRC_ACCOUNT;
42  }
43 
44  // No point in going any further if the transaction fee is malformed.
45  auto const fee = ctx.tx.getFieldAmount(sfFee);
46  if (!fee.native() || fee != beast::zero)
47  {
48  JLOG(ctx.j.warn()) << "Change: invalid fee";
49  return temBAD_FEE;
50  }
51 
52  if (!ctx.tx.getSigningPubKey().empty() || !ctx.tx.getSignature().empty() ||
54  {
55  JLOG(ctx.j.warn()) << "Change: Bad signature";
56  return temBAD_SIGNATURE;
57  }
58 
59  if (ctx.tx.getSequence() != 0 || ctx.tx.isFieldPresent(sfPreviousTxnID))
60  {
61  JLOG(ctx.j.warn()) << "Change: Bad sequence";
62  return temBAD_SEQUENCE;
63  }
64 
65  return tesSUCCESS;
66 }
67 
68 TER
70 {
71  // If tapOPEN_LEDGER is resurrected into ApplyFlags,
72  // this block can be moved to preflight.
73  if (ctx.view.open())
74  {
75  JLOG(ctx.j.warn()) << "Change transaction against open ledger";
76  return temINVALID;
77  }
78 
79  if (ctx.tx.getTxnType() != ttAMENDMENT && ctx.tx.getTxnType() != ttFEE)
80  return temUNKNOWN;
81 
82  return tesSUCCESS;
83 }
84 
85 TER
87 {
88  if (ctx_.tx.getTxnType() == ttAMENDMENT)
89  return applyAmendment();
90 
91  assert(ctx_.tx.getTxnType() == ttFEE);
92  return applyFee();
93 }
94 
95 void
97 {
99  assert(account_ == beast::zero);
100 }
101 
102 TER
104 {
105  uint256 amendment(ctx_.tx.getFieldH256(sfAmendment));
106 
107  auto const k = keylet::amendments();
108 
109  SLE::pointer amendmentObject = view().peek(k);
110 
111  if (!amendmentObject)
112  {
113  amendmentObject = std::make_shared<SLE>(k);
114  view().insert(amendmentObject);
115  }
116 
117  STVector256 amendments = amendmentObject->getFieldV256(sfAmendments);
118 
119  if (std::find(amendments.begin(), amendments.end(), amendment) !=
120  amendments.end())
121  return tefALREADY;
122 
123  auto flags = ctx_.tx.getFlags();
124 
125  const bool gotMajority = (flags & tfGotMajority) != 0;
126  const bool lostMajority = (flags & tfLostMajority) != 0;
127 
128  if (gotMajority && lostMajority)
129  return temINVALID_FLAG;
130 
131  STArray newMajorities(sfMajorities);
132 
133  bool found = false;
134  if (amendmentObject->isFieldPresent(sfMajorities))
135  {
136  const STArray& oldMajorities =
137  amendmentObject->getFieldArray(sfMajorities);
138  for (auto const& majority : oldMajorities)
139  {
140  if (majority.getFieldH256(sfAmendment) == amendment)
141  {
142  if (gotMajority)
143  return tefALREADY;
144  found = true;
145  }
146  else
147  {
148  // pass through
149  newMajorities.push_back(majority);
150  }
151  }
152  }
153 
154  if (!found && lostMajority)
155  return tefALREADY;
156 
157  if (gotMajority)
158  {
159  // This amendment now has a majority
160  newMajorities.push_back(STObject(sfMajority));
161  auto& entry = newMajorities.back();
162  entry.emplace_back(STHash256(sfAmendment, amendment));
163  entry.emplace_back(STUInt32(
164  sfCloseTime, view().parentCloseTime().time_since_epoch().count()));
165 
166  if (!ctx_.app.getAmendmentTable().isSupported(amendment))
167  {
168  JLOG(j_.warn()) << "Unsupported amendment " << amendment
169  << " received a majority.";
170  }
171  }
172  else if (!lostMajority)
173  {
174  // No flags, enable amendment
175  amendments.push_back(amendment);
176  amendmentObject->setFieldV256(sfAmendments, amendments);
177 
178  ctx_.app.getAmendmentTable().enable(amendment);
179 
180  if (!ctx_.app.getAmendmentTable().isSupported(amendment))
181  {
182  JLOG(j_.error()) << "Unsupported amendment " << amendment
183  << " activated: server blocked.";
185  }
186  }
187 
188  if (newMajorities.empty())
189  amendmentObject->makeFieldAbsent(sfMajorities);
190  else
191  amendmentObject->setFieldArray(sfMajorities, newMajorities);
192 
193  view().update(amendmentObject);
194 
195  return tesSUCCESS;
196 }
197 
198 TER
200 {
201  auto const k = keylet::fees();
202 
203  SLE::pointer feeObject = view().peek(k);
204 
205  if (!feeObject)
206  {
207  feeObject = std::make_shared<SLE>(k);
208  view().insert(feeObject);
209  }
210 
211  feeObject->setFieldU64(sfBaseFee, ctx_.tx.getFieldU64(sfBaseFee));
212  feeObject->setFieldU32(
214  feeObject->setFieldU32(sfReserveBase, ctx_.tx.getFieldU32(sfReserveBase));
215  feeObject->setFieldU32(
217 
218  view().update(feeObject);
219 
220  JLOG(j_.warn()) << "Fees have been changed";
221  return tesSUCCESS;
222 }
223 
224 } // namespace ripple
ripple::STArray::empty
bool empty() const
Definition: STArray.h:144
ripple::STTx::getTxnType
TxType getTxnType() const
Definition: STTx.h:105
std::shared_ptr< STLedgerEntry >
ripple::PreclaimContext::view
ReadView const & view
Definition: Transactor.h:57
ripple::keylet::amendments
Keylet const & amendments() noexcept
The index of the amendment table.
Definition: Indexes.cpp:150
ripple::PreclaimContext::j
const beast::Journal j
Definition: Transactor.h:61
ripple::ApplyView::peek
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
ripple::sfSigners
const SField sfSigners(access, STI_ARRAY, 3, "Signers", SField::sMD_Default, SField::notSigning)
Definition: SField.h:511
ripple::Transactor::j_
const beast::Journal j_
Definition: Transactor.h:90
ripple::isTesSuccess
bool isTesSuccess(TER x)
Definition: TER.h:576
ripple::STObject::getFieldU64
std::uint64_t getFieldU64(SField const &field) const
Definition: STObject.cpp:538
ripple::Application::getAmendmentTable
virtual AmendmentTable & getAmendmentTable()=0
std::find
T find(T... args)
ripple::STUInt32
STInteger< std::uint32_t > STUInt32
Definition: STInteger.h:114
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:476
ripple::sfMajorities
const SField sfMajorities(access, STI_ARRAY, 16, "Majorities")
Definition: SField.h:518
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::STArray::push_back
void push_back(STObject const &object)
Definition: STArray.h:102
ripple::Change::preCompute
void preCompute() override
Definition: Change.cpp:96
ripple::NetworkOPs::setAmendmentBlocked
virtual void setAmendmentBlocked()=0
ripple::ApplyView::update
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
ripple::tfLostMajority
const std::uint32_t tfLostMajority
Definition: TxFlags.h:102
ripple::PreflightContext::j
const beast::Journal j
Definition: Transactor.h:39
ripple::sfReserveBase
const SF_U32 sfReserveBase(access, STI_UINT32, 31, "ReserveBase")
Definition: SField.h:383
ripple::tfGotMajority
const std::uint32_t tfGotMajority
Definition: TxFlags.h:101
ripple::Application::getOPs
virtual NetworkOPs & getOPs()=0
ripple::sfMajority
const SField sfMajority(access, STI_OBJECT, 18, "Majority")
Definition: SField.h:506
ripple::ApplyContext::app
Application & app
Definition: ApplyContext.h:47
ripple::ttFEE
@ ttFEE
Definition: TxFormats.h:60
ripple::base_uint< 256 >
ripple::temINVALID_FLAG
@ temINVALID_FLAG
Definition: TER.h:106
ripple::preflight0
NotTEC preflight0(PreflightContext const &ctx)
Performs early sanity checks on the txid.
Definition: Transactor.cpp:40
ripple::STObject::getAccountID
AccountID getAccountID(SField const &field) const
Definition: STObject.cpp:562
ripple::sfAmendment
const SF_U256 sfAmendment(access, STI_HASH256, 19, "Amendment")
Definition: SField.h:430
ripple::TERSubset< CanCvtToTER >
ripple::STArray
Definition: STArray.h:28
ripple::temBAD_SEQUENCE
@ temBAD_SEQUENCE
Definition: TER.h:99
ripple::temBAD_SRC_ACCOUNT
@ temBAD_SRC_ACCOUNT
Definition: TER.h:101
ripple::Change::doApply
TER doApply() override
Definition: Change.cpp:86
beast::Journal::error
Stream error() const
Definition: Journal.h:333
ripple::sfReferenceFeeUnits
const SF_U32 sfReferenceFeeUnits(access, STI_UINT32, 30, "ReferenceFeeUnits")
Definition: SField.h:382
ripple::STObject::getFlags
std::uint32_t getFlags() const
Definition: STObject.cpp:454
ripple::STTx::getSigningPubKey
Blob getSigningPubKey() const
Definition: STTx.h:111
ripple::temBAD_SIGNATURE
@ temBAD_SIGNATURE
Definition: TER.h:100
ripple::temUNKNOWN
@ temUNKNOWN
Definition: TER.h:119
ripple::ttAMENDMENT
@ ttAMENDMENT
Definition: TxFormats.h:59
ripple::AmendmentTable::enable
virtual bool enable(uint256 const &amendment)=0
ripple::AmendmentTable::isSupported
virtual bool isSupported(uint256 const &amendment)=0
ripple::temBAD_FEE
@ temBAD_FEE
Definition: TER.h:87
ripple::STHash256
STBitString< 256 > STHash256
Definition: STBitString.h:129
ripple::sfFee
const SF_Amount sfFee(access, STI_AMOUNT, 8, "Fee")
Definition: SField.h:446
ripple::PreclaimContext::tx
STTx const & tx
Definition: Transactor.h:59
ripple::STTx::getSequence
std::uint32_t getSequence() const
Definition: STTx.h:117
ripple::STArray::back
STObject & back()
Definition: STArray.h:83
ripple::Change::preclaim
static TER preclaim(PreclaimContext const &ctx)
Definition: Change.cpp:69
ripple::PreclaimContext
State information when determining if a tx is likely to claim a fee.
Definition: Transactor.h:53
ripple::Change::applyAmendment
TER applyAmendment()
Definition: Change.cpp:103
ripple::STObject::emplace_back
std::size_t emplace_back(Args &&... args)
Definition: STObject.h:384
ripple::Change::preflight
static NotTEC preflight(PreflightContext const &ctx)
Definition: Change.cpp:31
ripple::STObject
Definition: STObject.h:51
ripple::ApplyView::insert
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Transactor::view
ApplyView & view()
Definition: Transactor.h:107
ripple::sfReserveIncrement
const SF_U32 sfReserveIncrement(access, STI_UINT32, 32, "ReserveIncrement")
Definition: SField.h:384
ripple::STTx::getSignature
Blob getSignature() const
Definition: STTx.cpp:151
ripple::tefALREADY
@ tefALREADY
Definition: TER.h:143
ripple::STObject::isFieldPresent
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:401
ripple::sfCloseTime
const SF_U32 sfCloseTime(access, STI_UINT32, 7, "CloseTime")
Definition: SField.h:358
ripple::STVector256
Definition: STVector256.h:29
std::vector::empty
T empty(T... args)
ripple::Transactor::ctx_
ApplyContext & ctx_
Definition: Transactor.h:89
ripple::Transactor::account_
AccountID account_
Definition: Transactor.h:92
ripple::keylet::fees
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition: Indexes.cpp:158
ripple::sfAmendments
const SF_Vec256 sfAmendments(access, STI_VECTOR256, 3, "Amendments")
Definition: SField.h:491
ripple::PreflightContext::tx
STTx const & tx
Definition: Transactor.h:36
ripple::STObject::getFieldU32
std::uint32_t getFieldU32(SField const &field) const
Definition: STObject.cpp:532
ripple::PreflightContext
State information when preflighting a tx.
Definition: Transactor.h:32
ripple::sfBaseFee
const SF_U64 sfBaseFee(access, STI_UINT64, 5, "BaseFee")
Definition: SField.h:398
ripple::Change::applyFee
TER applyFee()
Definition: Change.cpp:199
ripple::ReadView::open
virtual bool open() const =0
Returns true if this reflects an open ledger.
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:213
ripple::STObject::getFieldAmount
STAmount const & getFieldAmount(SField const &field) const
Definition: STObject.cpp:576
ripple::sfPreviousTxnID
const SF_U256 sfPreviousTxnID(access, STI_HASH256, 5, "PreviousTxnID", SField::sMD_DeleteFinal)
Definition: SField.h:420
ripple::ApplyContext::tx
STTx const & tx
Definition: ApplyContext.h:48
ripple::temINVALID
@ temINVALID
Definition: TER.h:105
ripple::NotTEC
TERSubset< CanCvtToNotTEC > NotTEC
Definition: TER.h:507
ripple::STObject::getFieldH256
uint256 getFieldH256(SField const &field) const
Definition: STObject.cpp:556