1+ #include " ../chainparams.h"
2+ #include " ../script/standard.h"
3+ #include " ../validation.h"
4+ #include " ../wallet/coincontrol.h"
5+ #include " ../wallet/wallet.h"
6+ #include " ../net.h"
7+ #include " ../sparkname.h"
8+
9+ #include " test_bitcoin.h"
10+ #include " fixtures.h"
11+ #include < iostream>
12+ #include < boost/test/unit_test.hpp>
13+
14+ namespace spark {
15+
16+ class SparkNameTests : public SparkTestingSetup
17+ {
18+ public:
19+ SparkNameTests () :
20+ SparkTestingSetup (),
21+ sparkState (CSparkState::GetState()),
22+ consensus (::Params().GetConsensus()),
23+ sparkNameManager (CSparkNameManager::GetInstance()) {
24+ }
25+
26+ ~SparkNameTests () {
27+ sparkState->Reset ();
28+ }
29+
30+ bool IsSparkNamePresent (std::string const &name) {
31+ std::string address;
32+ return sparkNameManager->GetSparkAddress (name, address);
33+ }
34+
35+ std::string GetSparkNameAdditionalData (const std::string &name) {
36+ BOOST_CHECK (IsSparkNamePresent (name));
37+ return sparkNameManager->GetSparkNameAdditionalData (name);
38+ }
39+
40+ void Initialize () {
41+ std::vector<CMutableTransaction> mintTxs;
42+ GenerateBlocks (2000 -1 );
43+ GenerateMints ({50 * COIN, 60 * COIN, 10 *COIN, 10 *COIN, 10 *COIN}, mintTxs);
44+ GenerateBlock (mintTxs);
45+ pwalletMain->SetBroadcastTransactions (true );
46+ }
47+
48+ std::string GenerateSparkAddress () {
49+ const spark::Params *params = spark::Params::get_default ();
50+ spark::Address address (params);
51+
52+ LOCK (pwalletMain->cs_wallet );
53+ address = pwalletMain->sparkWallet ->generateNewAddress ();
54+ unsigned char network = spark::GetNetworkType ();
55+ std::string sparkAddressStr = address.encode (network);
56+
57+ pwalletMain->SetSparkAddressBook (sparkAddressStr, " " , " receive" );
58+ return sparkAddressStr;
59+ }
60+
61+ CMutableTransaction CreateSparkNameTx (CSparkNameTxData &sparkNameData, bool fCommit = false , CAmount sparkNameFee = 0 ) {
62+ LOCK (cs_main);
63+ LOCK (pwalletMain->cs_wallet );
64+
65+ CAmount txFee;
66+ size_t additionalSize = sparkNameManager->GetSparkNameTxDataSize (sparkNameData);
67+
68+ if (sparkNameFee == 0 ) {
69+ BOOST_ASSERT (sparkNameData.name .length () <= CSparkNameManager::maximumSparkNameLength);
70+ int numberOfYears = (sparkNameData.sparkNameValidityBlocks + 24 * 24 * 365 - 1 ) / (24 * 24 * 365 );
71+ sparkNameFee = consensus.nSparkNamesFee [sparkNameData.name .length ()] * COIN * numberOfYears;
72+ }
73+
74+ CWalletTx sparkNameWalletTx = pwalletMain->sparkWallet ->CreateSparkNameTransaction (sparkNameData, sparkNameFee, txFee, nullptr );
75+ if (fCommit ) {
76+ CReserveKey reserveKey (pwalletMain);
77+ lastState = CValidationState ();
78+ pwalletMain->CommitTransaction (sparkNameWalletTx, reserveKey, g_connman.get (), lastState);
79+ }
80+ return CMutableTransaction (*sparkNameWalletTx.tx );
81+ }
82+
83+ CMutableTransaction CreateSparkNameTx (const std::string &name, const std::string &address, uint32_t sparkNameValidityHeight, const std::string &additionalInfo, bool fCommit = false , CAmount sparkNameFee = 0 ) {
84+ CSparkNameTxData sparkNameData;
85+ sparkNameData.name = name;
86+ sparkNameData.sparkAddress = address;
87+ sparkNameData.sparkNameValidityBlocks = sparkNameValidityHeight;
88+ sparkNameData.additionalInfo = additionalInfo;
89+
90+ return CreateSparkNameTx (sparkNameData, fCommit , sparkNameFee);
91+ }
92+
93+ void DisconnectAndInvalidate () {
94+ LOCK (cs_main);
95+ CBlockIndex *pindex = chainActive.Tip ();
96+ DisconnectBlocks (1 );
97+ CValidationState state;
98+ const CChainParams &chainparams = ::Params ();
99+ InvalidateBlock (state, chainparams, pindex);
100+ }
101+
102+ CSparkState *sparkState;
103+ Consensus::Params const &consensus;
104+
105+ CSparkNameManager *sparkNameManager;
106+ CValidationState lastState;
107+ };
108+
109+ } // namespace spark
110+
111+ BOOST_FIXTURE_TEST_SUITE (sparknames, spark::SparkNameTests)
112+
113+ BOOST_AUTO_TEST_CASE(general)
114+ {
115+ Initialize ();
116+
117+ std::string txaddress = GenerateSparkAddress ();
118+ CMutableTransaction tx = CreateSparkNameTx (" testname" , txaddress, 2 , " x" , true );
119+ GenerateBlock ({tx});
120+ BOOST_CHECK (IsSparkNamePresent (" testname" ));
121+ GenerateBlock ({});
122+ BOOST_CHECK (IsSparkNamePresent (" testname" ));
123+ GenerateBlock ({});
124+ BOOST_CHECK (!IsSparkNamePresent (" testname" ));
125+ // invalidate last block
126+ DisconnectAndInvalidate ();
127+ // spark name should reappear
128+ BOOST_CHECK (IsSparkNamePresent (" testname" ));
129+ DisconnectAndInvalidate ();
130+ // still there
131+ BOOST_CHECK (IsSparkNamePresent (" testname" ));
132+ DisconnectAndInvalidate ();
133+ // should be gone now
134+ BOOST_CHECK (!IsSparkNamePresent (" testname" ));
135+
136+ BOOST_CHECK_EQUAL (mempool.size (), 1 );
137+
138+ std::string tx2address = GenerateSparkAddress ();
139+ CMutableTransaction tx2 = CreateSparkNameTx (" testname2" , tx2address, 5 , " my data" , true );
140+ CreateSparkNameTx (" testname" , GenerateSparkAddress (), 100 , " my data" , true );
141+
142+ // testname2 should get into mempool, testname should not because of mempool conflict
143+ BOOST_CHECK_EQUAL (mempool.size (), 2 );
144+ BOOST_CHECK_EQUAL (mempool.sparkNames .count (" TESTNAME" ), 1 );
145+ BOOST_CHECK_EQUAL (mempool.sparkNames .count (" TESTNAME2" ), 1 );
146+ BOOST_CHECK (!lastState.IsValid ());
147+ BOOST_CHECK_EQUAL (lastState.GetRejectReason (), " txn-mempool-conflict" );
148+
149+ // usage of already used spark address (in mempool) should be rejected
150+ CreateSparkNameTx (" someothername" , tx2address, 100 , " my data" , true );
151+ BOOST_CHECK (!lastState.IsValid ());
152+ BOOST_CHECK_EQUAL (lastState.GetRejectReason (), " txn-mempool-conflict" );
153+
154+ GenerateBlock ({tx, tx2});
155+ BOOST_CHECK_EQUAL (mempool.size (), 0 );
156+ BOOST_CHECK (mempool.sparkNames .empty ());
157+
158+ BOOST_CHECK (IsSparkNamePresent (" testname" ));
159+ BOOST_CHECK (IsSparkNamePresent (" testname2" ));
160+
161+ BOOST_CHECK_EQUAL (GetSparkNameAdditionalData (" testname" ), " x" );
162+
163+ // should fail because of changed address
164+ CMutableTransaction txmodFail = CreateSparkNameTx (" testname" , GenerateSparkAddress (), 3 , " dataupdate" , true );
165+ BOOST_ASSERT (!lastState.IsValid ());
166+
167+ // modify additional info and extend validity
168+ CMutableTransaction txmod = CreateSparkNameTx (" testname" , txaddress, 3 , " dataupdate" , true );
169+ BOOST_ASSERT (lastState.IsValid ());
170+ GenerateBlock ({txmod});
171+
172+ BOOST_CHECK_EQUAL (GetSparkNameAdditionalData (" testname" ), " dataupdate" );
173+
174+ // roll back a block
175+ DisconnectBlocks (1 );
176+ BOOST_CHECK_EQUAL (GetSparkNameAdditionalData (" testname" ), " x" );
177+
178+ ReprocessBlocks (1 );
179+ BOOST_CHECK_EQUAL (GetSparkNameAdditionalData (" testname" ), " dataupdate" );
180+ GenerateBlocks (2 );
181+
182+ // testname should be still there (because of extension)
183+ BOOST_CHECK (IsSparkNamePresent (" testname" ));
184+
185+ // test using the same spark address now
186+ CMutableTransaction tx3 = CreateSparkNameTx (" testname3" , txaddress, 3 , " x" , true );
187+ BOOST_CHECK (!lastState.IsValid ());
188+
189+ // shouldn't get into the block as well
190+ int oldHeight = chainActive.Height ();
191+ GenerateBlock ({tx3});
192+ BOOST_CHECK_EQUAL (chainActive.Height (), oldHeight);
193+
194+ // one more block and testname should be gone
195+ GenerateBlock ({});
196+ BOOST_CHECK (!IsSparkNamePresent (" testname" ));
197+
198+ oldHeight = chainActive.Height ();
199+ // tx3 should go ahead now
200+ GenerateBlock ({tx3});
201+ BOOST_CHECK_EQUAL (chainActive.Height (), oldHeight+1 );
202+ }
203+
204+ BOOST_AUTO_TEST_SUITE_END ()
0 commit comments