Skip to content

Commit 179fb3b

Browse files
test: introduce basic unit tests for instantsend
1 parent 26ea618 commit 179fb3b

File tree

4 files changed

+114
-0
lines changed

4 files changed

+114
-0
lines changed

src/Makefile.test.include

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ BITCOIN_TESTS =\
111111
test/dynamic_activation_thresholds_tests.cpp \
112112
test/evo_assetlocks_tests.cpp \
113113
test/evo_deterministicmns_tests.cpp \
114+
test/evo_islock_tests.cpp \
114115
test/evo_mnhf_tests.cpp \
115116
test/evo_simplifiedmns_tests.cpp \
116117
test/evo_trivialvalidation.cpp \

src/chainparams.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,16 @@ std::optional<Consensus::LLMQParams> CChainParams::GetLLMQ(Consensus::LLMQType l
152152
return std::nullopt;
153153
}
154154

155+
std::optional<Consensus::LLMQParams> CChainParams::GetLLMQByName(std::string_view llmqName) const
156+
{
157+
for (const auto& llmq_param : consensus.llmqs) {
158+
if (llmq_param.name == llmqName) {
159+
return std::make_optional(llmq_param);
160+
}
161+
}
162+
return std::nullopt;
163+
}
164+
155165
/**
156166
* Main network on which people trade goods and services.
157167
*/

src/chainparams.h

+1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ class CChainParams
152152
int MinSporkKeys() const { return nMinSporkKeys; }
153153
int CreditPoolPeriodBlocks() const { return nCreditPoolPeriodBlocks; }
154154
[[nodiscard]] std::optional<Consensus::LLMQParams> GetLLMQ(Consensus::LLMQType llmqType) const;
155+
[[nodiscard]] std::optional<Consensus::LLMQParams> GetLLMQByName(std::string_view llmqName) const;
155156

156157
protected:
157158
CChainParams() {}

src/test/evo_islock_tests.cpp

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// instantsend_tests.cpp
2+
#include <boost/test/unit_test.hpp>
3+
#include <llmq/instantsend.h>
4+
#include <hash.h>
5+
#include <uint256.h>
6+
#include <primitives/transaction.h>
7+
#include <streams.h>
8+
#include <string_view>
9+
10+
// For constructing dummy outpoints using uint256S.
11+
#include <util/strencodings.h>
12+
13+
BOOST_AUTO_TEST_SUITE(instantsend_tests)
14+
15+
BOOST_AUTO_TEST_CASE(getrequestid)
16+
{
17+
// Create an empty InstantSendLock
18+
llmq::CInstantSendLock islock;
19+
20+
// Compute expected hash for an empty inputs vector.
21+
// Note: CInstantSendLock::GetRequestId() serializes the prefix "islock"
22+
// followed by the 'inputs' vector.
23+
{
24+
CHashWriter hw(SER_GETHASH, 0);
25+
hw << std::string_view("islock");
26+
hw << islock.inputs; // empty vector
27+
const uint256 expected = hw.GetHash();
28+
29+
BOOST_CHECK(islock.GetRequestId() == expected);
30+
}
31+
32+
// Now add two dummy inputs to the lock
33+
islock.inputs.clear();
34+
// Construct two dummy outpoints (using uint256S for a dummy hash)
35+
COutPoint op1(uint256S("0x0000000000000000000000000000000000000000000000000000000000000001"), 0);
36+
COutPoint op2(uint256S("0x0000000000000000000000000000000000000000000000000000000000000002"), 1);
37+
islock.inputs.push_back(op1);
38+
islock.inputs.push_back(op2);
39+
40+
{
41+
CHashWriter hw(SER_GETHASH, 0);
42+
hw << std::string_view("islock");
43+
hw << islock.inputs;
44+
const uint256 expected = hw.GetHash();
45+
46+
BOOST_CHECK(islock.GetRequestId() == expected);
47+
}
48+
}
49+
50+
BOOST_AUTO_TEST_CASE(deserialize_instantlock_from_realdata2)
51+
{
52+
// Expected values from the provided getislocks output:
53+
const std::string_view expectedTxidStr = "7b33968effa613e8ea9c1b5734c9bbbe467ff4650f8060caf8a5c213c6059d5b";
54+
const std::string_view expectedCycleHashStr = "000000000000000bbd0b1bb95540351e7ee99c5b08efde076b3d712a57ea74d6";
55+
const std::string_view expectedSignature = "997d0b36738a9eef46ceeb4405998ff7235317708f277402799ffe05258015cae9b6bae43683f992b2f50f70f8f0cb9c0f26af340b00903e93995c1345d1b2c5b697ebecdbe5811dd112e11889101dcb4553b2bc206ab304026b96c07dec4f24";
56+
const std::string_view cycleHash = "000000000000000bbd0b1bb95540351e7ee99c5b08efde076b3d712a57ea74d6";
57+
const std::string quorumHash = "0000000000000019756ecc9c9c5f476d3f66876b1dcfa5dde1ea82f0d99334a2";
58+
const std::string_view expectedSignHash = "6a3c37bc610c4efd5babd8941068a8eca9e7bec942fe175b8ca9cae31b67e838";
59+
// The serialized InstantSend lock from the "hex" field of getislocks:
60+
const std::string_view islockHex =
61+
"0101497915895c30eebfad0c5fcfb9e0e72308c7e92cd3749be2fd49c8320c4c58b6010000005b9d05c613c2a5f8ca60800f65f47f46bebbc934571b9ceae813a6ff8e96337bd674ea572a713d6b07deef085b9ce97e1e354055b91b0bbd0b00000000000000997d0b36738a9eef46ceeb4405998ff7235317708f277402799ffe05258015cae9b6bae43683f992b2f50f70f8f0cb9c0f26af340b00903e93995c1345d1b2c5b697ebecdbe5811dd112e11889101dcb4553b2bc206ab304026b96c07dec4f24";
62+
63+
// This islock was created with non-legacy. Using legacy will result in the signature being all zeros.
64+
bls::bls_legacy_scheme.store(false);
65+
66+
// Convert hex string to a byte vector and deserialize.
67+
std::vector<unsigned char> islockData = ParseHex(islockHex);
68+
CDataStream ss(islockData, SER_NETWORK, PROTOCOL_VERSION);
69+
llmq::CInstantSendLock islock;
70+
ss >> islock;
71+
72+
// Verify the calculated signHash
73+
auto signHash = llmq::BuildSignHash(Consensus::LLMQType::LLMQ_60_75, uint256S(quorumHash), islock.GetRequestId(), islock.txid);
74+
BOOST_CHECK_EQUAL(signHash.ToString(),
75+
expectedSignHash);
76+
77+
// Verify the txid field.
78+
BOOST_CHECK_EQUAL(islock.txid.ToString(), expectedTxidStr);
79+
80+
// Verify the cycleHash field.
81+
BOOST_CHECK_EQUAL(islock.cycleHash.ToString(), expectedCycleHashStr);
82+
83+
// Verify the inputs vector has exactly one element.
84+
BOOST_REQUIRE_EQUAL(islock.inputs.size(), 1U);
85+
const COutPoint& input = islock.inputs.front();
86+
const std::string expectedInputTxid = "b6584c0c32c849fde29b74d32ce9c70823e7e0b9cf5f0cadbfee305c89157949";
87+
const unsigned int expectedInputN = 1;
88+
BOOST_CHECK_EQUAL(input.hash.ToString(), expectedInputTxid);
89+
BOOST_CHECK_EQUAL(input.n, expectedInputN);
90+
91+
// Compute the expected request ID: it is the hash of the constant prefix "islock" followed by the inputs.
92+
CHashWriter hw(SER_GETHASH, 0);
93+
hw << std::string_view("islock");
94+
hw << islock.inputs;
95+
uint256 expectedRequestId = hw.GetHash();
96+
BOOST_CHECK_EQUAL(islock.GetRequestId().ToString(), expectedRequestId.ToString());
97+
98+
// Verify the signature field.
99+
BOOST_CHECK_EQUAL(islock.sig.Get().ToString(), expectedSignature);
100+
}
101+
102+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)