rippled
NFTokenUtils.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2021 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 #ifndef RIPPLE_TX_IMPL_DETAILS_NFTOKENUTILS_H_INCLUDED
21 #define RIPPLE_TX_IMPL_DETAILS_NFTOKENUTILS_H_INCLUDED
22 
23 #include <ripple/basics/base_uint.h>
24 #include <ripple/basics/tagged_integer.h>
25 #include <ripple/ledger/ApplyView.h>
26 #include <ripple/protocol/AccountID.h>
27 #include <ripple/protocol/TER.h>
28 
29 namespace ripple {
30 
31 namespace nft {
32 
33 // Separate taxons from regular integers.
34 struct TaxonTag
35 {
36 };
38 
39 inline Taxon
41 {
42  return static_cast<Taxon>(i);
43 }
44 
45 inline std::uint32_t
47 {
48  return static_cast<std::uint32_t>(t);
49 }
50 
51 constexpr std::uint16_t const flagBurnable = 0x0001;
52 constexpr std::uint16_t const flagOnlyXRP = 0x0002;
53 constexpr std::uint16_t const flagCreateTrustLines = 0x0004;
54 constexpr std::uint16_t const flagTransferable = 0x0008;
55 
57 void
58 removeAllTokenOffers(ApplyView& view, Keylet const& directory);
59 
61 TER
62 notTooManyOffers(ReadView const& view, uint256 const& nftokenID);
63 
66 findToken(
67  ReadView const& view,
68  AccountID const& owner,
69  uint256 const& nftokenID);
70 
73 {
76 
78  : token(token_), page(std::move(page_))
79  {
80  }
81 };
84  ApplyView& view,
85  AccountID const& owner,
86  uint256 const& nftokenID);
87 
89 TER
90 insertToken(ApplyView& view, AccountID owner, STObject&& nft);
91 
93 TER
94 removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID);
95 
96 TER
98  ApplyView& view,
99  AccountID const& owner,
100  uint256 const& nftokenID,
101  std::shared_ptr<SLE>&& page);
102 
112 bool
113 deleteTokenOffer(ApplyView& view, std::shared_ptr<SLE> const& offer);
114 
115 inline std::uint16_t
116 getFlags(uint256 const& id)
117 {
118  std::uint16_t flags;
119  memcpy(&flags, id.begin(), 2);
120  return boost::endian::big_to_native(flags);
121 }
122 
123 inline std::uint16_t
125 {
126  std::uint16_t fee;
127  memcpy(&fee, id.begin() + 2, 2);
128  return boost::endian::big_to_native(fee);
129 }
130 
131 inline std::uint32_t
132 getSerial(uint256 const& id)
133 {
134  std::uint32_t seq;
135  memcpy(&seq, id.begin() + 28, 4);
136  return boost::endian::big_to_native(seq);
137 }
138 
139 inline Taxon
141 {
142  // An issuer may issue several NFTs with the same taxon; to ensure that NFTs
143  // are spread across multiple pages we lightly mix the taxon up by using the
144  // sequence (which is not under the issuer's direct control) as the seed for
145  // a simple linear congruential generator.
146  //
147  // From the Hull-Dobell theorem we know that f(x)=(m*x+c) mod n will yield a
148  // permutation of [0, n) when n is a power of 2 if m is congruent to 1 mod 4
149  // and c is odd.
150  //
151  // Here we use m = 384160001 and c = 2459. The modulo is implicit because we
152  // use 2^32 for n and the arithmetic gives it to us for "free".
153  //
154  // Note that the scramble value we calculate is not cryptographically secure
155  // but that's fine since all we're looking for is some dispersion.
156  //
157  // **IMPORTANT** Changing these numbers would be a breaking change requiring
158  // an amendment along with a way to distinguish token IDs that
159  // were generated with the old code.
160  return taxon ^ toTaxon(((384160001 * tokenSeq) + 2459));
161 }
162 
163 inline Taxon
164 getTaxon(uint256 const& id)
165 {
166  std::uint32_t taxon;
167  memcpy(&taxon, id.begin() + 24, 4);
168  taxon = boost::endian::big_to_native(taxon);
169 
170  // The taxon cipher is just an XOR, so it is reversible by applying the
171  // XOR a second time.
172  return cipheredTaxon(getSerial(id), toTaxon(taxon));
173 }
174 
175 inline AccountID
176 getIssuer(uint256 const& id)
177 {
178  return AccountID::fromVoid(id.data() + 4);
179 }
180 
181 bool
182 compareTokens(uint256 const& a, uint256 const& b);
183 
184 } // namespace nft
185 
186 } // namespace ripple
187 
188 #endif // RIPPLE_TX_IMPL_DETAILS_NFTOKENUTILS_H_INCLUDED
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::nft::getFlags
std::uint16_t getFlags(uint256 const &id)
Definition: NFTokenUtils.h:116
std::shared_ptr
STL class.
ripple::nft::TokenAndPage::page
std::shared_ptr< SLE > page
Definition: NFTokenUtils.h:75
ripple::nft::findTokenAndPage
std::optional< TokenAndPage > findTokenAndPage(ApplyView &view, AccountID const &owner, uint256 const &nftokenID)
Definition: NFTokenUtils.cpp:502
ripple::nft::TokenAndPage
Finds the token in the owner's token directory.
Definition: NFTokenUtils.h:72
ripple::nft::flagTransferable
constexpr const std::uint16_t flagTransferable
Definition: NFTokenUtils.h:54
ripple::nft::notTooManyOffers
TER notTooManyOffers(ReadView const &view, uint256 const &nftokenID)
Returns tesSUCCESS if NFToken has few enough offers that it can be burned.
Definition: NFTokenUtils.cpp:554
ripple::nft::TokenAndPage::token
STObject token
Definition: NFTokenUtils.h:74
ripple::nft::flagOnlyXRP
constexpr const std::uint16_t flagOnlyXRP
Definition: NFTokenUtils.h:52
ripple::nft::findToken
std::optional< STObject > findToken(ReadView const &view, AccountID const &owner, uint256 const &nftokenID)
Finds the specified token in the owner's token directory.
Definition: NFTokenUtils.cpp:480
ripple::nft::toTaxon
Taxon toTaxon(std::uint32_t i)
Definition: NFTokenUtils.h:40
ripple::nft::removeToken
TER removeToken(ApplyView &view, AccountID const &owner, uint256 const &nftokenID)
Remove the token from the owner's token directory.
Definition: NFTokenUtils.cpp:346
ripple::nft::compareTokens
bool compareTokens(uint256 const &a, uint256 const &b)
Definition: NFTokenUtils.cpp:224
ripple::ApplyView
Writeable view to a ledger, for applying a transaction.
Definition: ApplyView.h:134
ripple::nft::getIssuer
AccountID getIssuer(uint256 const &id)
Definition: NFTokenUtils.h:176
ripple::base_uint< 256 >
ripple::nft::TokenAndPage::TokenAndPage
TokenAndPage(STObject const &token_, std::shared_ptr< SLE > page_)
Definition: NFTokenUtils.h:77
ripple::nft::toUInt32
std::uint32_t toUInt32(Taxon t)
Definition: NFTokenUtils.h:46
ripple::TERSubset< CanCvtToTER >
ripple::nft::getSerial
std::uint32_t getSerial(uint256 const &id)
Definition: NFTokenUtils.h:132
std::uint32_t
ripple::nft::flagBurnable
constexpr const std::uint16_t flagBurnable
Definition: NFTokenUtils.h:51
ripple::STObject
Definition: STObject.h:51
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::nft::Taxon
tagged_integer< std::uint32_t, TaxonTag > Taxon
Definition: NFTokenUtils.h:37
std
STL namespace.
ripple::nft::removeAllTokenOffers
void removeAllTokenOffers(ApplyView &view, Keylet const &directory)
Deletes all offers from the specified token offer directory.
Definition: NFTokenUtils.cpp:524
ripple::base_uint< 160, detail::AccountIDTag >::fromVoid
static base_uint fromVoid(void const *data)
Definition: base_uint.h:311
ripple::nft::TaxonTag
Definition: NFTokenUtils.h:34
ripple::nft::flagCreateTrustLines
constexpr const std::uint16_t flagCreateTrustLines
Definition: NFTokenUtils.h:53
std::optional
ripple::tagged_integer
A type-safe wrap around standard integral types.
Definition: tagged_integer.h:44
ripple::nft::getTransferFee
std::uint16_t getTransferFee(uint256 const &id)
Definition: NFTokenUtils.h:124
ripple::nft::cipheredTaxon
Taxon cipheredTaxon(std::uint32_t tokenSeq, Taxon taxon)
Definition: NFTokenUtils.h:140
ripple::nft::getTaxon
Taxon getTaxon(uint256 const &id)
Definition: NFTokenUtils.h:164
ripple::nft::insertToken
TER insertToken(ApplyView &view, AccountID owner, STObject &&nft)
Insert the token in the owner's token directory.
Definition: NFTokenUtils.cpp:240
ripple::nft::deleteTokenOffer
bool deleteTokenOffer(ApplyView &view, std::shared_ptr< SLE > const &offer)
Deletes the given token offer.
Definition: NFTokenUtils.cpp:581