xrpld
Loading...
Searching...
No Matches
nft.h
1#pragma once
2
3#include <xrpl/basics/base_uint.h>
4#include <xrpl/basics/tagged_integer.h>
5#include <xrpl/protocol/AccountID.h>
6
7#include <boost/endian/conversion.hpp>
8
9#include <cstdint>
10#include <cstring>
11
12namespace xrpl::nft {
13
14// Separate taxons from regular integers.
16{
17};
19
20inline Taxon
22{
23 return static_cast<Taxon>(i);
24}
25
26inline std::uint32_t
28{
29 return static_cast<std::uint32_t>(t);
30}
31
32constexpr std::uint16_t const kFlagBurnable = 0x0001;
33constexpr std::uint16_t const kFlagOnlyXrp = 0x0002;
34constexpr std::uint16_t const kFlagCreateTrustLines = 0x0004;
35constexpr std::uint16_t const kFlagTransferable = 0x0008;
36constexpr std::uint16_t const kFlagMutable = 0x0010;
37
38inline std::uint16_t
39getFlags(uint256 const& id)
40{
41 std::uint16_t flags = 0;
42 memcpy(&flags, id.begin(), 2);
43 return boost::endian::big_to_native(flags);
44}
45
46inline std::uint16_t
48{
49 std::uint16_t fee = 0;
50 memcpy(&fee, id.begin() + 2, 2);
51 return boost::endian::big_to_native(fee);
52}
53
54inline std::uint32_t
56{
57 std::uint32_t seq = 0;
58 memcpy(&seq, id.begin() + 28, 4);
59 return boost::endian::big_to_native(seq);
60}
61
62inline Taxon
64{
65 // An issuer may issue several NFTs with the same taxon; to ensure that NFTs
66 // are spread across multiple pages we lightly mix the taxon up by using the
67 // sequence (which is not under the issuer's direct control) as the seed for
68 // a simple linear congruential generator.
69 //
70 // From the Hull-Dobell theorem we know that f(x)=(m*x+c) mod n will yield a
71 // permutation of [0, n) when n is a power of 2 if m is congruent to 1 mod 4
72 // and c is odd.
73 //
74 // Here we use m = 384160001 and c = 2459. The modulo is implicit because we
75 // use 2^32 for n and the arithmetic gives it to us for "free".
76 //
77 // Note that the scramble value we calculate is not cryptographically secure
78 // but that's fine since all we're looking for is some dispersion.
79 //
80 // **IMPORTANT** Changing these numbers would be a breaking change requiring
81 // an amendment along with a way to distinguish token IDs that
82 // were generated with the old code.
83 return taxon ^ toTaxon(((384160001 * tokenSeq) + 2459));
84}
85
86inline Taxon
87getTaxon(uint256 const& id)
88{
89 std::uint32_t taxon = 0;
90 memcpy(&taxon, id.begin() + 24, 4);
91 taxon = boost::endian::big_to_native(taxon);
92
93 // The taxon cipher is just an XOR, so it is reversible by applying the
94 // XOR a second time.
95 return cipheredTaxon(getSequence(id), toTaxon(taxon));
96}
97
98inline AccountID
100{
101 return AccountID::fromVoid(id.data() + 4);
102}
103
104} // namespace xrpl::nft
static BaseUInt fromVoid(void const *data)
Definition base_uint.h:322
A type-safe wrap around standard integral types.
std::uint32_t toUInt32(Taxon t)
Definition nft.h:27
constexpr std::uint16_t const kFlagCreateTrustLines
Definition nft.h:34
Taxon getTaxon(uint256 const &id)
Definition nft.h:87
constexpr std::uint16_t const kFlagTransferable
Definition nft.h:35
Taxon toTaxon(std::uint32_t i)
Definition nft.h:21
Taxon cipheredTaxon(std::uint32_t tokenSeq, Taxon taxon)
Definition nft.h:63
constexpr std::uint16_t const kFlagOnlyXrp
Definition nft.h:33
std::uint32_t getSequence(uint256 const &id)
Definition nft.h:55
constexpr std::uint16_t const kFlagMutable
Definition nft.h:36
AccountID getIssuer(uint256 const &id)
Definition nft.h:99
std::uint16_t getTransferFee(uint256 const &id)
Definition nft.h:47
constexpr std::uint16_t const kFlagBurnable
Definition nft.h:32
TaggedInteger< std::uint32_t, TaxonTag > Taxon
Definition nft.h:18
std::uint16_t getFlags(uint256 const &id)
Definition nft.h:39
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
BaseUInt< 256 > uint256
Definition base_uint.h:562