Raven Core  3.0.0
P2P Digital Currency
tx_verify.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2017 The Bitcoin Core developers
2 // Copyright (c) 2017-2019 The Raven Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <assets/assets.h>
7 #include <script/standard.h>
8 #include <util.h>
9 #include <validation.h>
10 #include "tx_verify.h"
11 
12 #include "consensus.h"
13 #include "primitives/transaction.h"
14 #include "script/interpreter.h"
15 #include "validation.h"
16 #include <cmath>
17 #include <wallet/wallet.h>
18 #include <base58.h>
19 #include <tinyformat.h>
20 
21 // TODO remove the following dependencies
22 #include "chain.h"
23 #include "coins.h"
24 #include "utilmoneystr.h"
25 
26 bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
27 {
28  if (tx.nLockTime == 0)
29  return true;
30  if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
31  return true;
32  for (const auto& txin : tx.vin) {
33  if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
34  return false;
35  }
36  return true;
37 }
38 
39 std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
40 {
41  assert(prevHeights->size() == tx.vin.size());
42 
43  // Will be set to the equivalent height- and time-based nLockTime
44  // values that would be necessary to satisfy all relative lock-
45  // time constraints given our view of block chain history.
46  // The semantics of nLockTime are the last invalid height/time, so
47  // use -1 to have the effect of any height or time being valid.
48  int nMinHeight = -1;
49  int64_t nMinTime = -1;
50 
51  // tx.nVersion is signed integer so requires cast to unsigned otherwise
52  // we would be doing a signed comparison and half the range of nVersion
53  // wouldn't support BIP 68.
54  bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
55  && flags & LOCKTIME_VERIFY_SEQUENCE;
56 
57  // Do not enforce sequence numbers as a relative lock time
58  // unless we have been instructed to
59  if (!fEnforceBIP68) {
60  return std::make_pair(nMinHeight, nMinTime);
61  }
62 
63  for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
64  const CTxIn& txin = tx.vin[txinIndex];
65 
66  // Sequence numbers with the most significant bit set are not
67  // treated as relative lock-times, nor are they given any
68  // consensus-enforced meaning at this point.
70  // The height of this input is not relevant for sequence locks
71  (*prevHeights)[txinIndex] = 0;
72  continue;
73  }
74 
75  int nCoinHeight = (*prevHeights)[txinIndex];
76 
78  int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
79  // NOTE: Subtract 1 to maintain nLockTime semantics
80  // BIP 68 relative lock times have the semantics of calculating
81  // the first block or time at which the transaction would be
82  // valid. When calculating the effective block time or height
83  // for the entire transaction, we switch to using the
84  // semantics of nLockTime which is the last invalid block
85  // time or height. Thus we subtract 1 from the calculated
86  // time or height.
87 
88  // Time-based relative lock-times are measured from the
89  // smallest allowed timestamp of the block containing the
90  // txout being spent, which is the median time past of the
91  // block prior.
92  nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
93  } else {
94  nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
95  }
96  }
97 
98  return std::make_pair(nMinHeight, nMinTime);
99 }
100 
101 bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
102 {
103  assert(block.pprev);
104  int64_t nBlockTime = block.pprev->GetMedianTimePast();
105  if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
106  return false;
107 
108  return true;
109 }
110 
111 bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
112 {
113  return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
114 }
115 
116 unsigned int GetLegacySigOpCount(const CTransaction& tx)
117 {
118  unsigned int nSigOps = 0;
119  for (const auto& txin : tx.vin)
120  {
121  nSigOps += txin.scriptSig.GetSigOpCount(false);
122  }
123  for (const auto& txout : tx.vout)
124  {
125  nSigOps += txout.scriptPubKey.GetSigOpCount(false);
126  }
127  return nSigOps;
128 }
129 
130 unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
131 {
132  if (tx.IsCoinBase())
133  return 0;
134 
135  unsigned int nSigOps = 0;
136  for (unsigned int i = 0; i < tx.vin.size(); i++)
137  {
138  const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
139  assert(!coin.IsSpent());
140  const CTxOut &prevout = coin.out;
141  if (prevout.scriptPubKey.IsPayToScriptHash())
142  nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
143  }
144  return nSigOps;
145 }
146 
147 int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
148 {
149  int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;
150 
151  if (tx.IsCoinBase())
152  return nSigOps;
153 
154  if (flags & SCRIPT_VERIFY_P2SH) {
155  nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
156  }
157 
158  for (unsigned int i = 0; i < tx.vin.size(); i++)
159  {
160  const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
161  assert(!coin.IsSpent());
162  const CTxOut &prevout = coin.out;
163  nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);
164  }
165  return nSigOps;
166 }
167 
168 bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
169 {
170  // Basic checks that don't depend on any context
171  if (tx.vin.empty())
172  return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
173  if (tx.vout.empty())
174  return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
175  // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
176  if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > GetMaxBlockWeight())
177  return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
178 
179  // Check for negative or overflow output values
180  CAmount nValueOut = 0;
181  std::set<std::string> setAssetTransferNames;
182  std::map<std::pair<std::string, std::string>, int> mapNullDataTxCount; // (asset_name, address) -> int
183  std::set<std::string> setNullGlobalAssetChanges;
184  bool fContainsNewRestrictedAsset = false;
185  bool fContainsRestrictedAssetReissue = false;
186  bool fContainsNullAssetVerifierTx = false;
187  int nCountAddTagOuts = 0;
188  for (const auto& txout : tx.vout)
189  {
190  if (txout.nValue < 0)
191  return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
192  if (txout.nValue > MAX_MONEY)
193  return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
194  nValueOut += txout.nValue;
195  if (!MoneyRange(nValueOut))
196  return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
197 
199  // Find and handle all new OP_RVN_ASSET null data transactions
200  if (txout.scriptPubKey.IsNullAsset()) {
201  CNullAssetTxData data;
202  std::string address;
203  std::string strError = "";
204 
205  if (txout.scriptPubKey.IsNullAssetTxDataScript()) {
206  if (!AssetNullDataFromScript(txout.scriptPubKey, data, address))
207  return state.DoS(100, false, REJECT_INVALID, "bad-txns-null-asset-data-serialization");
208 
209  if (!VerifyNullAssetDataFlag(data.flag, strError))
210  return state.DoS(100, false, REJECT_INVALID, strError);
211 
212  auto pair = std::make_pair(data.asset_name, address);
213  if(!mapNullDataTxCount.count(pair)){
214  mapNullDataTxCount.insert(std::make_pair(pair, 0));
215  }
216 
217  mapNullDataTxCount.at(pair)++;
218 
219  if (mapNullDataTxCount.at(pair) > 1)
220  return state.DoS(100, false, REJECT_INVALID, "bad-txns-null-data-only-one-change-per-asset-address");
221 
222  // For each qualifier that is added, there is a burn fee
223  if (IsAssetNameAQualifier(data.asset_name)) {
224  if (data.flag == (int)QualifierType::ADD_QUALIFIER) {
225  nCountAddTagOuts++;
226  }
227  }
228 
229  } else if (txout.scriptPubKey.IsNullGlobalRestrictionAssetTxDataScript()) {
230  if (!GlobalAssetNullDataFromScript(txout.scriptPubKey, data))
231  return state.DoS(100, false, REJECT_INVALID, "bad-txns-null-global-asset-data-serialization");
232 
233  if (!VerifyNullAssetDataFlag(data.flag, strError))
234  return state.DoS(100, false, REJECT_INVALID, strError);
235 
236  if (setNullGlobalAssetChanges.count(data.asset_name)) {
237  return state.DoS(100, false, REJECT_INVALID, "bad-txns-null-data-only-one-global-change-per-asset-name");
238  }
239 
240  setNullGlobalAssetChanges.insert(data.asset_name);
241 
242  } else if (txout.scriptPubKey.IsNullAssetVerifierTxDataScript()) {
243 
244  if (!CheckVerifierAssetTxOut(txout, strError))
245  return state.DoS(100, false, REJECT_INVALID, strError);
246 
247  if (fContainsNullAssetVerifierTx)
248  return state.DoS(100, false, REJECT_INVALID, "bad-txns-null-data-only-one-verifier-per-tx");
249 
250  fContainsNullAssetVerifierTx = true;
251  }
252  }
256  bool isAsset = false;
257  int nType;
258  bool fIsOwner;
259  if (txout.scriptPubKey.IsAssetScript(nType, fIsOwner))
260  isAsset = true;
261 
262  // Make sure that all asset tx have a nValue of zero RVN
263  if (isAsset && txout.nValue != 0)
264  return state.DoS(100, false, REJECT_INVALID, "bad-txns-asset-tx-amount-isn't-zero");
265 
266  // Check for transfers that don't meet the assets units only if the assetCache is not null
267  if (isAsset) {
268  // Get the transfer transaction data from the scriptPubKey
269  if (nType == TX_TRANSFER_ASSET) {
271  std::string address;
272  if (!TransferAssetFromScript(txout.scriptPubKey, transfer, address))
273  return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-asset-bad-deserialize");
274 
275  // insert into set, so that later on we can check asset null data transactions
276  setAssetTransferNames.insert(transfer.strName);
277 
278  // Check asset name validity and get type
279  AssetType assetType;
280  if (!IsAssetNameValid(transfer.strName, assetType)) {
281  return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-asset-name-invalid");
282  }
283 
284  // If the transfer is an ownership asset. Check to make sure that it is OWNER_ASSET_AMOUNT
285  if (IsAssetNameAnOwner(transfer.strName)) {
286  if (transfer.nAmount != OWNER_ASSET_AMOUNT)
287  return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-owner-amount-was-not-1");
288  }
289 
290  // If the transfer is a unique asset. Check to make sure that it is UNIQUE_ASSET_AMOUNT
291  if (assetType == AssetType::UNIQUE) {
292  if (transfer.nAmount != UNIQUE_ASSET_AMOUNT)
293  return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-unique-amount-was-not-1");
294  }
295 
296  // If the transfer is a restricted channel asset.
297  if (assetType == AssetType::RESTRICTED) {
298  // TODO add checks here if any
299  }
300 
301  // If the transfer is a qualifier channel asset.
302  if (assetType == AssetType::QUALIFIER || assetType == AssetType::SUB_QUALIFIER) {
304  return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-qualifier-amount-must be between 1 - 100");
305  }
306  }
307  }
308  }
309 
310  // Check for Add Tag Burn Fee
311  if (nCountAddTagOuts) {
312  if (!tx.CheckAddingTagBurnFee(nCountAddTagOuts))
313  return state.DoS(100, false, REJECT_INVALID, "bad-txns-tx-doesn't-contain-required-burn-fee-for-adding-tags");
314  }
315 
316  for (auto entry: mapNullDataTxCount) {
317  if (entry.first.first.front() == RESTRICTED_CHAR) {
318  std::string ownerToken = entry.first.first.substr(1, entry.first.first.size()); // $TOKEN into TOKEN
319  if (!setAssetTransferNames.count(ownerToken + OWNER_TAG)) {
320  return state.DoS(100, false, REJECT_INVALID, "bad-txns-tx-contains-restricted-asset-null-tx-without-asset-transfer");
321  }
322  } else { // must be a qualifier asset QUALIFIER_CHAR
323  if (!setAssetTransferNames.count(entry.first.first)) {
324  return state.DoS(100, false, REJECT_INVALID,
325  "bad-txns-tx-contains-qualifier-asset-null-tx-without-asset-transfer");
326  }
327  }
328  }
329 
330  for (auto name: setNullGlobalAssetChanges) {
331  std::string rootName = name.substr(1, name.size()); // $TOKEN into TOKEN
332  if (!setAssetTransferNames.count(rootName + OWNER_TAG)) {
333  return state.DoS(100, false, REJECT_INVALID, "bad-txns-tx-contains-global-asset-null-tx-without-asset-transfer");
334  }
335  }
336 
337 
340  if (fCheckDuplicateInputs) {
341  std::set<COutPoint> vInOutPoints;
342  for (const auto& txin : tx.vin)
343  {
344  if (!vInOutPoints.insert(txin.prevout).second)
345  return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
346  }
347  }
348 
349  if (tx.IsCoinBase())
350  {
351  if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
352  return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
353  }
354  else
355  {
356  for (const auto& txin : tx.vin)
357  if (txin.prevout.IsNull())
358  return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
359  }
360 
362  if (tx.IsNewAsset()) {
364  std::string strError = "";
365  if(!tx.VerifyNewAsset(strError))
366  return state.DoS(100, false, REJECT_INVALID, strError);
367 
368  CNewAsset asset;
369  std::string strAddress;
370  if (!AssetFromTransaction(tx, asset, strAddress))
371  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-asset-from-transaction");
372 
373  // Validate the new assets information
374  if (!IsNewOwnerTxValid(tx, asset.strName, strAddress, strError))
375  return state.DoS(100, false, REJECT_INVALID, strError);
376 
377  if(!CheckNewAsset(asset, strError))
378  return state.DoS(100, false, REJECT_INVALID, strError);
379 
380  } else if (tx.IsReissueAsset()) {
381 
383  std::string strError;
384  if (!tx.VerifyReissueAsset(strError))
385  return state.DoS(100, false, REJECT_INVALID, strError);
386 
388  std::string strAddress;
389  if (!ReissueAssetFromTransaction(tx, reissue, strAddress))
390  return state.DoS(100, false, REJECT_INVALID, "bad-txns-reissue-asset");
391 
392  if (!CheckReissueAsset(reissue, strError))
393  return state.DoS(100, false, REJECT_INVALID, strError);
394 
395  // Get the assetType
396  AssetType type;
397  IsAssetNameValid(reissue.strName, type);
398 
399  // If this is a reissuance of a restricted asset, mark it as such, so we can check to make sure only valid verifier string tx are added to the chain
400  if (type == AssetType::RESTRICTED) {
401  CNullAssetTxVerifierString new_verifier;
402  bool fNotFound = false;
403 
404  // Try and get the verifier string if it was changed
405  if (!tx.GetVerifierStringFromTx(new_verifier, strError, fNotFound)) {
406  // If it return false for any other reason besides not being found, fail the transaction check
407  if (!fNotFound) {
408  return state.DoS(100, false, REJECT_INVALID,
409  "bad-txns-reissue-restricted-verifier-" + strError);
410  }
411  }
412 
413  fContainsRestrictedAssetReissue = true;
414  }
415 
416  } else if (tx.IsNewUniqueAsset()) {
417 
419  std::string strError = "";
420  if (!tx.VerifyNewUniqueAsset(strError)) {
421  return state.DoS(100, false, REJECT_INVALID, strError);
422  }
423 
424 
425  for (auto out : tx.vout)
426  {
427  if (IsScriptNewUniqueAsset(out.scriptPubKey))
428  {
429  CNewAsset asset;
430  std::string strAddress;
431  if (!AssetFromScript(out.scriptPubKey, asset, strAddress))
432  return state.DoS(100, false, REJECT_INVALID, "bad-txns-check-transaction-issue-unique-asset-serialization");
433 
434  if (!CheckNewAsset(asset, strError))
435  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-unique" + strError);
436  }
437  }
438  } else if (tx.IsNewMsgChannelAsset()) {
440  std::string strError = "";
441  if(!tx.VerifyNewMsgChannelAsset(strError))
442  return state.DoS(100, false, REJECT_INVALID, strError);
443 
444  CNewAsset asset;
445  std::string strAddress;
446  if (!MsgChannelAssetFromTransaction(tx, asset, strAddress))
447  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-msgchannel-from-transaction");
448 
449  if (!CheckNewAsset(asset, strError))
450  return state.DoS(100, error("%s: %s", __func__, strError), REJECT_INVALID, "bad-txns-issue-msgchannel" + strError);
451 
452  } else if (tx.IsNewQualifierAsset()) {
454  std::string strError = "";
455  if(!tx.VerifyNewQualfierAsset(strError))
456  return state.DoS(100, false, REJECT_INVALID, strError);
457 
458  CNewAsset asset;
459  std::string strAddress;
460  if (!QualifierAssetFromTransaction(tx, asset, strAddress))
461  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-qualifier-from-transaction");
462 
463  if (!CheckNewAsset(asset, strError))
464  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-qualfier" + strError);
465 
466  } else if (tx.IsNewRestrictedAsset()) {
468  std::string strError = "";
469  if(!tx.VerifyNewRestrictedAsset(strError))
470  return state.DoS(100, false, REJECT_INVALID, strError);
471 
472  // Get asset data
473  CNewAsset asset;
474  std::string strAddress;
475  if (!RestrictedAssetFromTransaction(tx, asset, strAddress))
476  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-restricted-from-transaction");
477 
478  if (!CheckNewAsset(asset, strError))
479  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-restricted" + strError);
480 
481  // Get verifier string
483  if (!tx.GetVerifierStringFromTx(verifier, strError))
484  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-restricted-verifier-search-" + strError);
485 
486  // Mark that this transaction has a restricted asset issuance, for checks later with the verifier string tx
487  fContainsNewRestrictedAsset = true;
488  }
489  else {
490  // Fail if transaction contains any non-transfer asset scripts and hasn't conformed to one of the
491  // above transaction types. Also fail if it contains OP_RVN_ASSET opcode but wasn't a valid script.
492  for (auto out : tx.vout) {
493  int nType;
494  bool _isOwner;
495  if (out.scriptPubKey.IsAssetScript(nType, _isOwner)) {
496  if (nType != TX_TRANSFER_ASSET) {
497  return state.DoS(100, false, REJECT_INVALID, "bad-txns-bad-asset-transaction");
498  }
499  } else {
500  if (out.scriptPubKey.Find(OP_RVN_ASSET)) {
501  if (out.scriptPubKey[0] != OP_RVN_ASSET) {
502  return state.DoS(100, false, REJECT_INVALID,
503  "bad-txns-op-rvn-asset-not-in-right-script-location");
504  }
505  }
506  }
507  }
508  }
509 
510  // Check to make sure that if there is a verifier string, that there is also a issue or reissuance of a restricted asset
511  if (fContainsNullAssetVerifierTx && !fContainsRestrictedAssetReissue && !fContainsNewRestrictedAsset)
512  return state.DoS(100, false, REJECT_INVALID, "bad-txns-tx-cointains-verifier-string-without-restricted-asset-issuance-or-reissuance");
513 
514  // If there is a restricted asset issuance, verify that there is a verifier tx associated with it.
515  if (fContainsNewRestrictedAsset && !fContainsNullAssetVerifierTx) {
516  return state.DoS(100, false, REJECT_INVALID, "bad-txns-tx-cointains-restricted-asset-issuance-without-verifier");
517  }
518 
519  // we allow restricted asset reissuance without having a verifier string transaction, we don't force it to be update
522  return true;
523 }
524 
525 bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
526 {
527  // are the actual inputs available?
528  if (!inputs.HaveInputs(tx)) {
529  return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-missingorspent", false,
530  strprintf("%s: inputs missing/spent", __func__));
531  }
532 
533  CAmount nValueIn = 0;
534  for (unsigned int i = 0; i < tx.vin.size(); ++i) {
535  const COutPoint &prevout = tx.vin[i].prevout;
536  const Coin& coin = inputs.AccessCoin(prevout);
537  assert(!coin.IsSpent());
538 
539  // If prev is coinbase, check that it's matured
540  if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
541  return state.Invalid(false,
542  REJECT_INVALID, "bad-txns-premature-spend-of-coinbase",
543  strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
544  }
545 
546  // Check for negative or overflow input values
547  nValueIn += coin.out.nValue;
548  if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
549  return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
550  }
551  }
552 
553  const CAmount value_out = tx.GetValueOut();
554  if (nValueIn < value_out) {
555  return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false,
556  strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
557  }
558 
559  // Tally transaction fees
560  const CAmount txfee_aux = nValueIn - value_out;
561  if (!MoneyRange(txfee_aux)) {
562  return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-out-of-range");
563  }
564 
565  txfee = txfee_aux;
566  return true;
567 }
568 
570 bool Consensus::CheckTxAssets(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, CAssetsCache* assetCache, bool fCheckMempool, std::vector<std::pair<std::string, uint256> >& vPairReissueAssets, const bool fRunningUnitTests, std::set<CMessage>* setMessages, int64_t nBlocktime)
571 {
572  // are the actual inputs available?
573  if (!inputs.HaveInputs(tx)) {
574  return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-missing-or-spent", false,
575  strprintf("%s: inputs missing/spent", __func__));
576  }
577 
578  // Create map that stores the amount of an asset transaction input. Used to verify no assets are burned
579  std::map<std::string, CAmount> totalInputs;
580 
581  std::map<std::string, std::string> mapAddresses;
582 
583  for (unsigned int i = 0; i < tx.vin.size(); ++i) {
584  const COutPoint &prevout = tx.vin[i].prevout;
585  const Coin& coin = inputs.AccessCoin(prevout);
586  assert(!coin.IsSpent());
587 
588  if (coin.IsAsset()) {
589  CAssetOutputEntry data;
590  if (!GetAssetData(coin.out.scriptPubKey, data))
591  return state.DoS(100, false, REJECT_INVALID, "bad-txns-failed-to-get-asset-from-script");
592 
593  // Add to the total value of assets in the inputs
594  if (totalInputs.count(data.assetName))
595  totalInputs.at(data.assetName) += data.nAmount;
596  else
597  totalInputs.insert(make_pair(data.assetName, data.nAmount));
598 
599  if (AreMessagingDeployed()) {
600  mapAddresses.insert(make_pair(data.assetName,EncodeDestination(data.destination)));
601  }
602 
604  if (assetCache->CheckForAddressRestriction(data.assetName, EncodeDestination(data.destination), true)) {
605  return state.DoS(100, false, REJECT_INVALID, "bad-txns-restricted-asset-transfer-from-frozen-address");
606  }
607  }
608  }
609  }
610 
611  // Create map that stores the amount of an asset transaction output. Used to verify no assets are burned
612  std::map<std::string, CAmount> totalOutputs;
613  int index = 0;
614  int64_t currentTime = GetTime();
615  std::string strError = "";
616  int i = 0;
617  for (const auto& txout : tx.vout) {
618  i++;
619  bool fIsAsset = false;
620  int nType = 0;
621  bool fIsOwner = false;
622  if (txout.scriptPubKey.IsAssetScript(nType, fIsOwner))
623  fIsAsset = true;
624 
625  if (assetCache) {
626  if (fIsAsset && !AreAssetsDeployed())
627  return state.DoS(100, false, REJECT_INVALID, "bad-txns-is-asset-and-asset-not-active");
628 
629  if (txout.scriptPubKey.IsNullAsset()) {
631  return state.DoS(100, false, REJECT_INVALID,
632  "bad-tx-null-asset-data-before-restricted-assets-activated");
633 
634  if (txout.scriptPubKey.IsNullAssetTxDataScript()) {
635  if (!ContextualCheckNullAssetTxOut(txout, assetCache, strError))
636  return state.DoS(100, false, REJECT_INVALID, strError);
637  } else if (txout.scriptPubKey.IsNullGlobalRestrictionAssetTxDataScript()) {
638  if (!ContextualCheckGlobalAssetTxOut(txout, assetCache, strError))
639  return state.DoS(100, false, REJECT_INVALID, strError);
640  } else if (txout.scriptPubKey.IsNullAssetVerifierTxDataScript()) {
641  if (!ContextualCheckVerifierAssetTxOut(txout, assetCache, strError))
642  return state.DoS(100, false, REJECT_INVALID, strError);
643  } else {
644  return state.DoS(100, false, REJECT_INVALID, "bad-tx-null-asset-data-unknown-type");
645  }
646  }
647  }
648 
649  if (nType == TX_TRANSFER_ASSET) {
651  std::string address = "";
652  if (!TransferAssetFromScript(txout.scriptPubKey, transfer, address))
653  return state.DoS(100, false, REJECT_INVALID, "bad-tx-asset-transfer-bad-deserialize");
654 
655  if (!ContextualCheckTransferAsset(assetCache, transfer, address, strError))
656  return state.DoS(100, false, REJECT_INVALID, strError);
657 
658  // Add to the total value of assets in the outputs
659  if (totalOutputs.count(transfer.strName))
660  totalOutputs.at(transfer.strName) += transfer.nAmount;
661  else
662  totalOutputs.insert(make_pair(transfer.strName, transfer.nAmount));
663 
664  if (!fRunningUnitTests) {
665  if (IsAssetNameAnOwner(transfer.strName)) {
666  if (transfer.nAmount != OWNER_ASSET_AMOUNT)
667  return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-owner-amount-was-not-1");
668  } else {
669  // For all other types of assets, make sure they are sending the right type of units
670  CNewAsset asset;
671  if (!assetCache->GetAssetMetaDataIfExists(transfer.strName, asset))
672  return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-asset-not-exist");
673 
674  if (asset.strName != transfer.strName)
675  return state.DoS(100, false, REJECT_INVALID, "bad-txns-asset-database-corrupted");
676 
677  if (!CheckAmountWithUnits(transfer.nAmount, asset.units))
678  return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-asset-amount-not-match-units");
679  }
680  }
681 
683  // Get the messages from the Tx unless they are expired
684  if (AreMessagingDeployed() && fMessaging && setMessages) {
685  if (IsAssetNameAnOwner(transfer.strName) || IsAssetNameAnMsgChannel(transfer.strName)) {
686  if (!transfer.message.empty()) {
687  if (transfer.nExpireTime == 0 || transfer.nExpireTime > currentTime) {
688  if (mapAddresses.count(transfer.strName)) {
689  if (mapAddresses.at(transfer.strName) == address) {
690  COutPoint out(tx.GetHash(), index);
691  CMessage message(out, transfer.strName, transfer.message,
692  transfer.nExpireTime, nBlocktime);
693  setMessages->insert(message);
694  LogPrintf("Got message: %s\n", message.ToString()); // TODO remove after testing
695  }
696  }
697  }
698  }
699  }
700  }
701  } else if (nType == TX_REISSUE_ASSET) {
703  std::string address;
704  if (!ReissueAssetFromScript(txout.scriptPubKey, reissue, address))
705  return state.DoS(100, false, REJECT_INVALID, "bad-tx-asset-reissue-bad-deserialize");
706 
707  if (mapReissuedAssets.count(reissue.strName)) {
708  if (mapReissuedAssets.at(reissue.strName) != tx.GetHash())
709  return state.DoS(100, false, REJECT_INVALID, "bad-tx-reissue-chaining-not-allowed");
710  } else {
711  vPairReissueAssets.emplace_back(std::make_pair(reissue.strName, tx.GetHash()));
712  }
713  }
714  index++;
715  }
716 
717  if (assetCache) {
718  if (tx.IsNewAsset()) {
719  // Get the asset type
720  CNewAsset asset;
721  std::string address;
722  if (!AssetFromScript(tx.vout[tx.vout.size() - 1].scriptPubKey, asset, address)) {
723  error("%s : Failed to get new asset from transaction: %s", __func__, tx.GetHash().GetHex());
724  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-serialzation-failed");
725  }
726 
727  AssetType assetType;
728  IsAssetNameValid(asset.strName, assetType);
729 
731  if (assetType == AssetType::SUB) {
732  std::string root = GetParentName(asset.strName);
733  bool fOwnerOutFound = false;
734  for (auto out : tx.vout) {
736  std::string transferAddress;
737  if (TransferAssetFromScript(out.scriptPubKey, transfer, transferAddress)) {
738  if (root + OWNER_TAG == transfer.strName) {
739  fOwnerOutFound = true;
740  break;
741  }
742  }
743  }
744 
745  if (!fOwnerOutFound) {
746  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-new-asset-missing-owner-asset");
747  }
748  }
749  }
750 
751  if (!ContextualCheckNewAsset(assetCache, asset, strError, fCheckMempool))
752  return state.DoS(100, false, REJECT_INVALID, strError);
753  } else if (tx.IsReissueAsset()) {
754  CReissueAsset reissue_asset;
755  std::string address;
756  if (!ReissueAssetFromScript(tx.vout[tx.vout.size() - 1].scriptPubKey, reissue_asset, address)) {
757  error("%s : Failed to get new asset from transaction: %s", __func__, tx.GetHash().GetHex());
758  return state.DoS(100, false, REJECT_INVALID, "bad-txns-reissue-serialzation-failed");
759  }
760  if (!ContextualCheckReissueAsset(assetCache, reissue_asset, strError, tx))
761  return state.DoS(100, false, REJECT_INVALID, "bad-txns-reissue-contextual-" + strError);
762  } else if (tx.IsNewUniqueAsset()) {
763  if (!ContextualCheckUniqueAssetTx(assetCache, strError, tx))
764  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-unique-contextual-" + strError);
765  } else if (tx.IsNewMsgChannelAsset()) {
766  if (!AreMessagingDeployed())
767  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-msgchannel-before-messaging-is-active");
768 
769  CNewAsset asset;
770  std::string strAddress;
771  if (!MsgChannelAssetFromTransaction(tx, asset, strAddress))
772  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-msgchannel-serialzation-failed");
773 
774  if (!ContextualCheckNewAsset(assetCache, asset, strError))
775  return state.DoS(100, error("%s: %s", __func__, strError), REJECT_INVALID,
776  "bad-txns-issue-msgchannel-contextual-" + strError);
777  } else if (tx.IsNewQualifierAsset()) {
779  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-qualifier-before-it-is-active");
780 
781  CNewAsset asset;
782  std::string strAddress;
783  if (!QualifierAssetFromTransaction(tx, asset, strAddress))
784  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-qualifier-serialzation-failed");
785 
786  if (!ContextualCheckNewAsset(assetCache, asset, strError))
787  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-qualfier-contextual" + strError);
788 
789  } else if (tx.IsNewRestrictedAsset()) {
791  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-restricted-before-it-is-active");
792 
793  // Get asset data
794  CNewAsset asset;
795  std::string strAddress;
796  if (!RestrictedAssetFromTransaction(tx, asset, strAddress))
797  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-restricted-serialzation-failed");
798 
799  if (!ContextualCheckNewAsset(assetCache, asset, strError))
800  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-restricted-contextual" + strError);
801 
802  // Get verifier string
804  if (!tx.GetVerifierStringFromTx(verifier, strError))
805  return state.DoS(100, false, REJECT_INVALID, "bad-txns-issue-restricted-verifier-search-" + strError);
806 
807  // Check the verifier string against the destination address
808  if (!ContextualCheckVerifierString(assetCache, verifier.verifier_string, strAddress, strError))
809  return state.DoS(100, false, REJECT_INVALID, strError);
810 
811  } else {
812  for (auto out : tx.vout) {
813  int nType;
814  bool _isOwner;
815  if (out.scriptPubKey.IsAssetScript(nType, _isOwner)) {
816  if (nType != TX_TRANSFER_ASSET) {
817  return state.DoS(100, false, REJECT_INVALID, "bad-txns-bad-asset-transaction");
818  }
819  } else {
820  if (out.scriptPubKey.Find(OP_RVN_ASSET)) {
822  if (out.scriptPubKey[0] != OP_RVN_ASSET) {
823  return state.DoS(100, false, REJECT_INVALID,
824  "bad-txns-op-rvn-asset-not-in-right-script-location");
825  }
826  } else {
827  return state.DoS(100, false, REJECT_INVALID, "bad-txns-bad-asset-script");
828  }
829  }
830  }
831  }
832  }
833  }
834 
835  for (const auto& outValue : totalOutputs) {
836  if (!totalInputs.count(outValue.first)) {
837  std::string errorMsg;
838  errorMsg = strprintf("Bad Transaction - Trying to create outpoint for asset that you don't have: %s", outValue.first);
839  return state.DoS(100, false, REJECT_INVALID, "bad-tx-inputs-outputs-mismatch " + errorMsg);
840  }
841 
842  if (totalInputs.at(outValue.first) != outValue.second) {
843  std::string errorMsg;
844  errorMsg = strprintf("Bad Transaction - Assets would be burnt %s", outValue.first);
845  return state.DoS(100, false, REJECT_INVALID, "bad-tx-inputs-outputs-mismatch " + errorMsg);
846  }
847  }
848 
849  // Check the input size and the output size
850  if (totalOutputs.size() != totalInputs.size()) {
851  return state.DoS(100, false, REJECT_INVALID, "bad-tx-asset-inputs-size-does-not-match-outputs-size");
852  }
853  return true;
854 }
bool QualifierAssetFromTransaction(const CTransaction &tx, CNewAsset &asset, std::string &strAddress)
Definition: assets.cpp:549
unsigned int GetSigOpCount(bool fAccurate) const
Pre-version-0.6, Raven always counted CHECKMULTISIGs as 20 sigops.
Definition: script.cpp:162
CAmount nValue
Definition: transaction.h:140
bool IsSpent() const
Definition: coins.h:78
#define OWNER_ASSET_AMOUNT
Definition: assets.h:35
#define UNIQUE_ASSET_AMOUNT
Definition: assets.h:36
RVN START.
Definition: script.h:188
bool CheckAddingTagBurnFee(const int &count) const
Definition: assets.cpp:1474
bool IsCoinBase() const
Definition: coins.h:57
bool IsNewOwnerTxValid(const CTransaction &tx, const std::string &assetName, const std::string &address, std::string &errorMsg)
Definition: assets.cpp:596
std::pair< int, int64_t > CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector< int > *prevHeights, const CBlockIndex &block)
Calculates the block height and previous block&#39;s median time past at which the transaction will be co...
Definition: tx_verify.cpp:39
std::string strName
Definition: assettypes.h:239
int8_t units
Definition: assettypes.h:102
CScript scriptPubKey
Definition: transaction.h:141
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:179
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or a pruned one if not found.
Definition: coins.cpp:390
bool IsNewRestrictedAsset() const
Make sure to call VerifyNewAsset if this call returns true.
Definition: assets.cpp:1253
int flags
Definition: raven-tx.cpp:500
bool ContextualCheckReissueAsset(CAssetsCache *assetCache, const CReissueAsset &reissue_asset, std::string &strError, const CTransaction &tx)
Definition: assets.cpp:5273
bool SequenceLocks(const CTransaction &tx, int flags, std::vector< int > *prevHeights, const CBlockIndex &block)
Check if transaction is final per BIP 68 sequence numbers and can be included in a block...
Definition: tx_verify.cpp:111
A UTXO entry.
Definition: coins.h:32
#define strprintf
Definition: tinyformat.h:1054
unsigned int GetMaxBlockWeight()
Definition: consensus.cpp:8
size_t CountWitnessSigOps(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags)
size_t GetSerializeSize(const T &t, int nType, int nVersion=0)
Definition: serialize.h:967
static const uint32_t SEQUENCE_FINAL
Only serialized through CTransaction.
Definition: transaction.h:77
bool AssetFromScript(const CScript &scriptPubKey, CNewAsset &assetNew, std::string &strAddress)
Definition: assets.cpp:664
bool MoneyRange(const CAmount &nValue)
Definition: amount.h:28
bool TransferAssetFromScript(const CScript &scriptPubKey, CAssetTransfer &assetTransfer, std::string &strAddress)
Get specific asset type metadata from the given scripts.
Definition: assets.cpp:638
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG
Definition: transaction.h:82
CTxOut out
unspent transaction output
Definition: coins.h:36
bool AssetFromTransaction(const CTransaction &tx, CNewAsset &asset, std::string &strAddress)
These types of asset tx, have specific metadata at certain indexes in the transaction.
Definition: assets.cpp:525
std::string strName
Definition: assettypes.h:100
static const int SEQUENCE_LOCKTIME_GRANULARITY
Definition: transaction.h:100
bool VerifyNewUniqueAsset(std::string &strError) const
Call this function after IsNewUniqueAsset.
Definition: assets.cpp:913
bool DoS(int level, bool ret=false, unsigned int chRejectCodeIn=0, const std::string &strRejectReasonIn="", bool corruptionIn=false, const std::string &strDebugMessageIn="")
Definition: validation.h:44
bool AssetNullDataFromScript(const CScript &scriptPubKey, CNullAssetTxData &assetData, std::string &strAddress)
Definition: assets.cpp:815
std::string strName
Definition: assettypes.h:190
bool ReissueAssetFromScript(const CScript &scriptPubKey, CReissueAsset &reissue, std::string &strAddress)
Definition: assets.cpp:789
bool HaveInputs(const CTransaction &tx) const
Check whether all prevouts of the transaction are present in the UTXO set represented by this view...
Definition: coins.cpp:507
bool IsNewQualifierAsset() const
Make sure to call VerifyNewQualifierAsset if this call returns true.
Definition: assets.cpp:1164
std::string asset_name
Definition: assettypes.h:278
bool IsCoinBase() const
Definition: transaction.h:360
bool IsNewAsset() const
RVN START.
Definition: assets.cpp:881
#define QUALIFIER_ASSET_MAX_AMOUNT
Definition: assets.h:44
const std::vector< CTxIn > vin
Definition: transaction.h:287
CAmount GetValueOut() const
Definition: transaction.cpp:92
RVN START.
Definition: wallet.h:191
bool GetAssetData(const CScript &script, CAssetOutputEntry &data)
Definition: assets.cpp:3440
bool IsAssetNameAnMsgChannel(const std::string &name)
Check if an asset is a message channel.
Definition: assets.cpp:311
int64_t CAmount
Amount in corbies (Can be negative)
Definition: amount.h:13
uint32_t nHeight
at which height this containing transaction was included in the active block chain ...
Definition: coins.h:42
bool AreMessagingDeployed()
bool GlobalAssetNullDataFromScript(const CScript &scriptPubKey, CNullAssetTxData &assetData)
Definition: assets.cpp:840
bool IsAssetNameValid(const std::string &name, AssetType &assetType, std::string &error)
Definition: assets.cpp:207
bool ContextualCheckVerifierAssetTxOut(const CTxOut &txout, CAssetsCache *assetCache, std::string &strError)
Definition: assets.cpp:4960
#define LogPrintf(...)
Definition: util.h:149
bool AreAssetsDeployed()
RVN START.
bool VerifyNewQualfierAsset(std::string &strError) const
To be called on CTransactions where IsNewQualifierAsset returns true.
Definition: assets.cpp:1177
UniValue transfer(const JSONRPCRequest &request)
Definition: assets.cpp:1101
bool VerifyNullAssetDataFlag(const int &flag, std::string &strError)
Helper methods that validate changes to null asset data transaction databases.
Definition: assets.cpp:4796
bool GetAssetMetaDataIfExists(const std::string &name, CNewAsset &asset)
Returns true if an asset with the name exists, and it was able to get the asset metadata from databas...
Definition: assets.cpp:3340
An input of a transaction.
Definition: transaction.h:67
bool MsgChannelAssetFromTransaction(const CTransaction &tx, CNewAsset &asset, std::string &strAddress)
Definition: assets.cpp:537
bool CheckTxInputs(const CTransaction &tx, CValidationState &state, const CCoinsViewCache &inputs, int nSpendHeight, CAmount &txfee)
Check whether all inputs of this transaction are valid (no double spends and amounts) This does not m...
Definition: tx_verify.cpp:525
bool ContextualCheckNewAsset(CAssetsCache *assetCache, const CNewAsset &asset, std::string &strError, bool fCheckMempool)
Definition: assets.cpp:5187
const uint256 & GetHash() const
Definition: transaction.h:320
#define OWNER_TAG
Definition: assets.h:32
bool ContextualCheckNullAssetTxOut(const CTxOut &txout, CAssetsCache *assetCache, std::string &strError)
Definition: assets.cpp:4915
std::string assetName
Definition: wallet.h:194
std::map< std::string, uint256 > mapReissuedAssets
Definition: assets.cpp:41
const std::vector< CTxOut > vout
Definition: transaction.h:288
bool EvaluateSequenceLocks(const CBlockIndex &block, std::pair< int, int64_t > lockPair)
Definition: tx_verify.cpp:101
bool ContextualCheckGlobalAssetTxOut(const CTxOut &txout, CAssetsCache *assetCache, std::string &strError)
Definition: assets.cpp:4943
An output of a transaction.
Definition: transaction.h:137
int64_t nExpireTime
Definition: assettypes.h:193
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG
Definition: transaction.h:87
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:22
bool GetVerifierStringFromTx(CNullAssetTxVerifierString &verifier, std::string &strError) const
Definition: assets.cpp:1378
std::string FormatMoney(const CAmount &n)
Money parsing/formatting utilities.
int64_t GetMedianTimePast() const
Definition: chain.h:311
bool RestrictedAssetFromTransaction(const CTransaction &tx, CNewAsset &asset, std::string &strAddress)
Definition: assets.cpp:560
bool AreRestrictedAssetsDeployed()
AssetType
Definition: assettypes.h:21
RVN END.
Definition: validation.h:30
const int32_t nVersion
Definition: transaction.h:289
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:326
static const uint32_t SEQUENCE_LOCKTIME_MASK
Definition: transaction.h:91
unsigned int GetLegacySigOpCount(const CTransaction &tx)
Auxiliary functions for transaction validation (ideally should not be exposed)
Definition: tx_verify.cpp:116
bool ReissueAssetFromTransaction(const CTransaction &tx, CReissueAsset &reissue, std::string &strAddress)
Definition: assets.cpp:572
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:172
bool IsNewMsgChannelAsset() const
Make sure to call VerifyNewUniqueAsset if this call returns true.
Definition: assets.cpp:1077
bool fMessaging
Definition: validation.cpp:82
uint32_t nSequence
Definition: transaction.h:72
bool CheckAmountWithUnits(const CAmount &nAmount, const int8_t nUnits)
Checks the amount and units, and makes sure that the amount uses the correct decimals.
Definition: assets.cpp:4277
std::string GetParentName(const std::string &name)
Get the root name of an asset.
Definition: assets.cpp:366
unsigned int GetP2SHSigOpCount(const CTransaction &tx, const CCoinsViewCache &inputs)
Count ECDSA signature operations in pay-to-script-hash inputs.
Definition: tx_verify.cpp:130
bool ContextualCheckVerifierString(CAssetsCache *cache, const std::string &verifier, const std::string &check_address, std::string &strError, bool fWithTags)
Definition: assets.cpp:4979
std::string message
Definition: assettypes.h:192
std::string GetHex() const
Definition: uint256.cpp:22
bool VerifyNewMsgChannelAsset(std::string &strError) const
To be called on CTransactions where IsNewAsset returns true.
Definition: assets.cpp:1090
bool IsAssetNameAQualifier(const std::string &name)
Check if an asset is a qualifier asset or sub qualifier.
Definition: assets.cpp:306
bool ContextualCheckTransferAsset(CAssetsCache *assetCache, const CAssetTransfer &transfer, const std::string &address, std::string &strError)
Definition: assets.cpp:5036
bool VerifyReissueAsset(std::string &strError) const
To be called on CTransactions where IsReissueAsset returns true.
Definition: assets.cpp:1394
bool error(const char *fmt, const Args &... args)
Definition: util.h:168
bool CheckTransaction(const CTransaction &tx, CValidationState &state, bool fCheckDuplicateInputs)
Transaction validation functions.
Definition: tx_verify.cpp:168
bool CheckVerifierAssetTxOut(const CTxOut &txout, std::string &strError)
Definition: assets.cpp:4888
bool CheckTxAssets(const CTransaction &tx, CValidationState &state, const CCoinsViewCache &inputs, CAssetsCache *assetCache, bool fCheckMempool, std::vector< std::pair< std::string, uint256 > > &vPairReissueAssets, const bool fRunningUnitTests=false, std::set< CMessage > *setMessages=nullptr, int64_t nBlocktime=0)
RVN START.
Definition: tx_verify.cpp:570
bool CheckReissueAsset(const CReissueAsset &asset, std::string &strError)
Definition: assets.cpp:5232
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
Check if transaction is final and can be included in a block with the specified height and time...
Definition: tx_verify.cpp:26
bool IsReissueAsset() const
Definition: assets.cpp:1384
#define RESTRICTED_CHAR
Definition: assets.h:40
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
Definition: utiltime.cpp:20
bool CheckForAddressRestriction(const std::string &restricted_name, const std::string &address, bool fSkipTempCache=false)
Return true if the address is marked as frozen.
Definition: assets.cpp:4593
CAmount nAmount
Definition: wallet.h:196
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:270
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:185
bool VerifyNewRestrictedAsset(std::string &strError) const
To be called on CTransactions where IsNewRestrictedAsset returns true.
Definition: assets.cpp:1266
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:208
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:84
bool IsAsset() const
Definition: coins.h:82
bool Invalid(bool ret=false, unsigned int _chRejectCode=0, const std::string &_strRejectReason="", const std::string &_strDebugMessage="")
Definition: validation.h:58
CTxDestination destination
Definition: wallet.h:195
bool IsNewUniqueAsset() const
Make sure to call VerifyNewUniqueAsset if this call returns true.
Definition: assets.cpp:900
bool VerifyNewAsset(std::string &strError) const
To be called on CTransactions where IsNewAsset returns true.
Definition: assets.cpp:1006
int64_t GetTransactionSigOpCost(const CTransaction &tx, const CCoinsViewCache &inputs, int flags)
Compute total signature operation cost of a transaction.
Definition: tx_verify.cpp:147
#define QUALIFIER_ASSET_MIN_AMOUNT
Definition: assets.h:43
CAmount nAmount
Definition: assettypes.h:191
bool ContextualCheckUniqueAssetTx(CAssetsCache *assetCache, std::string &strError, const CTransaction &tx)
Definition: assets.cpp:5416
UniValue reissue(const JSONRPCRequest &request)
Definition: assets.cpp:1465
const uint32_t nLockTime
Definition: transaction.h:290
bool IsAssetNameAnRestricted(const std::string &name)
Check if an asset is a restricted asset.
Definition: assets.cpp:301
bool IsAssetNameAnOwner(const std::string &name)
Check if an asset is an owner.
Definition: assets.cpp:296
bool IsScriptNewUniqueAsset(const CScript &scriptPubKey)
Check script and see if it matches the unquie issuance template.
Definition: assets.cpp:3117
bool CheckNewAsset(const CNewAsset &asset, std::string &strError)
Definition: assets.cpp:5105